mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Merge branch 'master' into calc
This commit is contained in:
commit
80d471d5cf
400 changed files with 8129 additions and 11782 deletions
|
@ -112,14 +112,12 @@ impl WebGLPaintTask {
|
|||
gl::enable_vertex_attrib_array(attrib_id),
|
||||
CanvasWebGLMsg::GetAttribLocation(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) =>
|
||||
self.get_shader_parameter(shader_id, param_id, chan),
|
||||
CanvasWebGLMsg::GetUniformLocation(program_id, name, chan) =>
|
||||
self.get_uniform_location(program_id, name, chan),
|
||||
CanvasWebGLMsg::CompileShader(shader_id) =>
|
||||
self.compile_shader(shader_id),
|
||||
CanvasWebGLMsg::CompileShader(shader_id, source) =>
|
||||
self.compile_shader(shader_id, source),
|
||||
CanvasWebGLMsg::CreateBuffer(chan) =>
|
||||
self.create_buffer(chan),
|
||||
CanvasWebGLMsg::CreateFramebuffer(chan) =>
|
||||
|
@ -154,8 +152,6 @@ impl WebGLPaintTask {
|
|||
gl::bind_texture(target, id),
|
||||
CanvasWebGLMsg::LinkProgram(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) =>
|
||||
gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]),
|
||||
CanvasWebGLMsg::UseProgram(program_id) =>
|
||||
|
@ -303,11 +299,9 @@ impl WebGLPaintTask {
|
|||
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]
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -323,13 +317,6 @@ impl WebGLPaintTask {
|
|||
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,
|
||||
shader_id: u32,
|
||||
param_id: u32,
|
||||
|
|
|
@ -138,7 +138,7 @@ pub enum CanvasWebGLMsg {
|
|||
DepthRange(f64, f64),
|
||||
Enable(u32),
|
||||
Disable(u32),
|
||||
CompileShader(u32),
|
||||
CompileShader(u32, String),
|
||||
CreateBuffer(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateFramebuffer(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateRenderbuffer(IpcSender<Option<NonZero<u32>>>),
|
||||
|
@ -157,7 +157,6 @@ pub enum CanvasWebGLMsg {
|
|||
BindTexture(u32, u32),
|
||||
DrawArrays(u32, i32, i32),
|
||||
EnableVertexAttribArray(u32),
|
||||
GetShaderInfoLog(u32, IpcSender<Option<String>>),
|
||||
GetShaderParameter(u32, u32, IpcSender<WebGLShaderParameter>),
|
||||
GetAttribLocation(u32, String, IpcSender<Option<i32>>),
|
||||
GetUniformLocation(u32, String, IpcSender<Option<i32>>),
|
||||
|
@ -166,7 +165,6 @@ pub enum CanvasWebGLMsg {
|
|||
LineWidth(f32),
|
||||
PixelStorei(u32, i32),
|
||||
LinkProgram(u32),
|
||||
ShaderSource(u32, String),
|
||||
Uniform4fv(i32, Vec<f32>),
|
||||
UseProgram(u32),
|
||||
VertexAttribPointer2f(u32, i32, bool, i32, u32),
|
||||
|
|
|
@ -54,8 +54,8 @@ use style::viewport::ViewportConstraints;
|
|||
use url::Url;
|
||||
use util::cursor::Cursor;
|
||||
use util::geometry::PagePx;
|
||||
use util::opts;
|
||||
use util::task::spawn_named;
|
||||
use util::{opts, prefs};
|
||||
|
||||
/// 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,
|
||||
subpage_id: SubpageId,
|
||||
event: MozBrowserEvent) {
|
||||
assert!(opts::experimental_enabled());
|
||||
assert!(prefs::get_pref("dom.mozbrowser.enabled", false));
|
||||
|
||||
// Find the script channel for the given parent pipeline,
|
||||
// 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
|
||||
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
|
||||
if opts::experimental_enabled() {
|
||||
if prefs::get_pref("dom.mozbrowser.enabled", false) {
|
||||
// Work around borrow checker
|
||||
let event_info = {
|
||||
let pipeline = self.pipeline(pipeline_id);
|
||||
|
|
|
@ -7,6 +7,7 @@ use windowing::WindowEvent;
|
|||
|
||||
use euclid::scale_factor::ScaleFactor;
|
||||
use euclid::size::Size2D;
|
||||
use msg::constellation_msg::AnimationState;
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use msg::constellation_msg::{ConstellationChan, WindowSizeData};
|
||||
use profile_traits::mem;
|
||||
|
@ -88,6 +89,18 @@ impl CompositorEventListener for NullCompositor {
|
|||
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,
|
||||
// we'll notice and think about whether it needs a response, like
|
||||
// SetFrameTree.
|
||||
|
@ -95,7 +108,6 @@ impl CompositorEventListener for NullCompositor {
|
|||
Msg::InitializeLayersForPipeline(..) |
|
||||
Msg::SetLayerRect(..) |
|
||||
Msg::AssignPaintedBuffers(..) |
|
||||
Msg::ChangeRunningAnimationsState(..) |
|
||||
Msg::ScrollFragmentPoint(..) |
|
||||
Msg::Status(..) |
|
||||
Msg::LoadStart(..) |
|
||||
|
|
|
@ -39,9 +39,9 @@ extern crate clipboard;
|
|||
extern crate time;
|
||||
extern crate url;
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate core_graphics;
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate core_text;
|
||||
|
||||
pub use compositor_task::{CompositorEventListener, CompositorProxy, CompositorTask};
|
||||
|
|
|
@ -31,7 +31,7 @@ use url::Url;
|
|||
use util;
|
||||
use util::geometry::{PagePx, ViewportPx};
|
||||
use util::ipc::OptionalIpcSender;
|
||||
use util::opts;
|
||||
use util::prefs;
|
||||
|
||||
/// A uniquely-identifiable pipeline of script task, layout task, and paint task.
|
||||
pub struct Pipeline {
|
||||
|
@ -269,7 +269,7 @@ impl Pipeline {
|
|||
pub fn trigger_mozbrowser_event(&self,
|
||||
subpage_id: SubpageId,
|
||||
event: MozBrowserEvent) {
|
||||
assert!(opts::experimental_enabled());
|
||||
assert!(prefs::get_pref("dom.mozbrowser.enabled", false));
|
||||
|
||||
let event = ConstellationControlMsg::MozBrowserEvent(self.id,
|
||||
subpage_id,
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
|
||||
use devtools_traits::PreciseTime;
|
||||
use rustc_serialize::json;
|
||||
use std::any::{Any, TypeId};
|
||||
use std::any::Any;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::marker::Reflect;
|
||||
use std::mem::{replace, transmute};
|
||||
use std::mem::replace;
|
||||
use std::net::TcpStream;
|
||||
use std::raw::TraitObject;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -24,7 +22,7 @@ pub enum ActorMessageStatus {
|
|||
/// A common trait for all devtools actors that encompasses an immutable name
|
||||
/// and the ability to process messages that are directed to particular actors.
|
||||
/// TODO: ensure the name is immutable
|
||||
pub trait Actor: Any {
|
||||
pub trait Actor: Any + ActorAsAny {
|
||||
fn handle_message(&self,
|
||||
registry: &ActorRegistry,
|
||||
msg_type: &str,
|
||||
|
@ -33,55 +31,14 @@ pub trait Actor: Any {
|
|||
fn name(&self) -> String;
|
||||
}
|
||||
|
||||
impl Actor + Send {
|
||||
/// Returns true if the boxed type is the same as `T`
|
||||
#[inline]
|
||||
pub fn is<T: Reflect + 'static>(&self) -> bool {
|
||||
// Get TypeId of the type this function is instantiated with
|
||||
let t = TypeId::of::<T>();
|
||||
trait ActorAsAny {
|
||||
fn actor_as_any(&self) -> &Any;
|
||||
fn actor_as_any_mut(&mut self) -> &mut Any;
|
||||
}
|
||||
|
||||
// Get TypeId of the type in the trait object
|
||||
let boxed = self.get_type_id();
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
impl<T: Actor> ActorAsAny for T {
|
||||
fn actor_as_any(&self) -> &Any { self }
|
||||
fn actor_as_any_mut(&mut self) -> &mut Any { self }
|
||||
}
|
||||
|
||||
/// A list of known, owned actors.
|
||||
|
@ -179,15 +136,15 @@ impl ActorRegistry {
|
|||
}
|
||||
|
||||
/// 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();
|
||||
actor.downcast_ref::<T>().unwrap()
|
||||
actor.actor_as_any().downcast_ref::<T>().unwrap()
|
||||
}
|
||||
|
||||
/// 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();
|
||||
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
|
||||
|
|
|
@ -17,9 +17,9 @@ use devtools_traits::EvaluateJSReply::{StringValue, BooleanValue, ActorValue};
|
|||
use devtools_traits::{CachedConsoleMessageTypes, DevtoolScriptControlMsg, PAGE_ERROR, CONSOLE_API};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
|
||||
use core::cell::RefCell;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use rustc_serialize::json::{self, Json, ToJson};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::net::TcpStream;
|
||||
use std::sync::mpsc::channel;
|
||||
|
|
|
@ -6,7 +6,6 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
|||
use msg::constellation_msg::PipelineId;
|
||||
use rustc_serialize::{json, Encoder, Encodable};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::net::TcpStream;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -17,7 +16,7 @@ use actors::framerate::FramerateActor;
|
|||
use actors::memory::{MemoryActor, TimelineMemoryReply};
|
||||
use devtools_traits::DevtoolScriptControlMsg;
|
||||
use devtools_traits::DevtoolScriptControlMsg::{SetTimelineMarkers, DropTimelineMarkers};
|
||||
use devtools_traits::{PreciseTime, TimelineMarker, TracingMetadata, TimelineMarkerType};
|
||||
use devtools_traits::{PreciseTime, TimelineMarker, TimelineMarkerType};
|
||||
use protocol::JsonPacketStream;
|
||||
use util::task;
|
||||
|
||||
|
@ -148,72 +147,15 @@ impl TimelineActor {
|
|||
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 || {
|
||||
let mut queues = HashMap::new();
|
||||
queues.insert("Reflow".to_string(), VecDeque::new());
|
||||
queues.insert("DOMEvent".to_string(), VecDeque::new());
|
||||
|
||||
loop {
|
||||
if !*is_recording.lock().unwrap() {
|
||||
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![];
|
||||
for (_, queue) in &mut queues {
|
||||
let start_payload = queue.pop_front();
|
||||
group(queue, 0, start_payload, &emitter, &mut markers);
|
||||
while let Ok(marker) = receiver.try_recv() {
|
||||
markers.push(emitter.marker(marker));
|
||||
}
|
||||
emitter.send(markers);
|
||||
|
||||
|
@ -336,14 +278,13 @@ impl Emitter {
|
|||
}
|
||||
}
|
||||
|
||||
fn marker(&self, start_payload: TimelineMarker, end_payload: TimelineMarker)
|
||||
-> TimelineMarkerReply {
|
||||
fn marker(&self, payload: TimelineMarker) -> TimelineMarkerReply {
|
||||
TimelineMarkerReply {
|
||||
name: start_payload.name,
|
||||
start: HighResolutionStamp::new(self.start_stamp, start_payload.time),
|
||||
end: HighResolutionStamp::new(self.start_stamp, end_payload.time),
|
||||
stack: start_payload.stack,
|
||||
endStack: end_payload.stack,
|
||||
name: payload.name,
|
||||
start: HighResolutionStamp::new(self.start_stamp, payload.start_time),
|
||||
end: HighResolutionStamp::new(self.start_stamp, payload.end_time),
|
||||
stack: payload.start_stack,
|
||||
endStack: payload.end_stack,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,12 +11,8 @@
|
|||
#![crate_type = "rlib"]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(core)]
|
||||
#![feature(custom_derive)]
|
||||
#![feature(get_type_id)]
|
||||
#![feature(plugin)]
|
||||
#![feature(raw)]
|
||||
#![feature(reflect_marker)]
|
||||
#![plugin(serde_macros)]
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
@ -25,7 +21,6 @@
|
|||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
extern crate core;
|
||||
extern crate devtools_traits;
|
||||
extern crate rustc_serialize;
|
||||
extern crate ipc_channel;
|
||||
|
|
|
@ -124,21 +124,19 @@ pub struct NodeInfo {
|
|||
pub incompleteValue: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum TracingMetadata {
|
||||
Default,
|
||||
IntervalStart,
|
||||
IntervalEnd,
|
||||
Event,
|
||||
EventBacktrace,
|
||||
pub struct StartedTimelineMarker {
|
||||
name: String,
|
||||
start_time: PreciseTime,
|
||||
start_stack: Option<Vec<()>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct TimelineMarker {
|
||||
pub name: String,
|
||||
pub metadata: TracingMetadata,
|
||||
pub time: PreciseTime,
|
||||
pub stack: Option<Vec<()>>,
|
||||
pub start_time: PreciseTime,
|
||||
pub start_stack: Option<Vec<()>>,
|
||||
pub end_time: PreciseTime,
|
||||
pub end_stack: Option<Vec<()>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
|
||||
|
@ -270,12 +268,23 @@ pub enum NetworkEvent {
|
|||
}
|
||||
|
||||
impl TimelineMarker {
|
||||
pub fn new(name: String, metadata: TracingMetadata) -> TimelineMarker {
|
||||
TimelineMarker {
|
||||
pub fn start(name: String) -> StartedTimelineMarker {
|
||||
StartedTimelineMarker {
|
||||
name: name,
|
||||
metadata: metadata,
|
||||
time: PreciseTime::now(),
|
||||
stack: None,
|
||||
start_time: PreciseTime::now(),
|
||||
start_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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,13 +101,13 @@ pub struct Font {
|
|||
|
||||
bitflags! {
|
||||
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,
|
||||
#[doc="Set if we are to ignore ligatures."]
|
||||
#[doc = "Set if we are to ignore ligatures."]
|
||||
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,
|
||||
#[doc="Text direction is right-to-left."]
|
||||
#[doc = "Text direction is right-to-left."]
|
||||
const RTL_FLAG = 0x08,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,16 +31,16 @@ use std::sync::Arc;
|
|||
use azure::azure_hl::BackendType;
|
||||
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;
|
||||
|
||||
#[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 {
|
||||
ScaledFont::new(BackendType::Skia, FontInfo::FontData(&template.bytes),
|
||||
pt_size.to_f32_px())
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
|
||||
let cgfont = template.ctfont().as_ref().unwrap().copy_to_CGFont();
|
||||
ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px())
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![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(custom_attribute)]
|
||||
#![feature(custom_derive)]
|
||||
#![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(plugin)]
|
||||
#![feature(str_char)]
|
||||
|
@ -55,23 +55,23 @@ extern crate canvas_traits;
|
|||
extern crate harfbuzz;
|
||||
|
||||
// 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;
|
||||
|
||||
#[cfg(any(target_os="linux", target_os = "android"))]
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
extern crate freetype;
|
||||
|
||||
// Mac OS-specific library dependencies
|
||||
#[cfg(target_os="macos")] extern crate core_foundation;
|
||||
#[cfg(target_os="macos")] extern crate core_graphics;
|
||||
#[cfg(target_os="macos")] extern crate core_text;
|
||||
#[cfg(target_os = "macos")] extern crate core_foundation;
|
||||
#[cfg(target_os = "macos")] extern crate core_graphics;
|
||||
#[cfg(target_os = "macos")] extern crate core_text;
|
||||
|
||||
pub use paint_context::PaintContext;
|
||||
|
||||
// Private painting modules
|
||||
mod paint_context;
|
||||
|
||||
#[path="display_list/mod.rs"]
|
||||
#[path = "display_list/mod.rs"]
|
||||
pub mod display_list;
|
||||
pub mod paint_task;
|
||||
|
||||
|
@ -85,7 +85,7 @@ pub mod font_template;
|
|||
mod filters;
|
||||
|
||||
// Platform-specific implementations.
|
||||
#[path="platform/mod.rs"]
|
||||
#[path = "platform/mod.rs"]
|
||||
pub mod platform;
|
||||
|
||||
// Text
|
||||
|
|
|
@ -72,6 +72,19 @@ enum DashSize {
|
|||
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> {
|
||||
pub fn draw_target(&self) -> &DrawTarget {
|
||||
&self.draw_target
|
||||
|
@ -355,6 +368,104 @@ impl<'a> PaintContext<'a> {
|
|||
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
|
||||
// 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_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_BR = rad_R + 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_TL = rad_L + 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> {
|
||||
Point2D::new(x, 0.)
|
||||
|
@ -475,12 +590,41 @@ impl<'a> PaintContext<'a> {
|
|||
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 {
|
||||
Direction::Top => {
|
||||
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_BR = edge_TR + dy(border.top);
|
||||
let edge_BL = edge_TL + dy(border.top);
|
||||
let edge_BR = box_TR + dx(-border.right - distance_to_elbow_TR) + 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_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.
|
||||
let origin = edge_TR + Point2D::new((border.right - radius.top_right).max(0.),
|
||||
radius.top_right);
|
||||
// the elbow is the inside of the border's curve.
|
||||
let distance_to_elbow = (radius.top_right - border.top).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, radius.top_right, rad_T, rad_TR, false);
|
||||
path_builder.arc(origin, distance_to_elbow, rad_TR, rad_T, true);
|
||||
path_builder.arc(origin, radius.top_right, rad_T, rad_R - angle, false);
|
||||
if distance_to_elbow_TR != 0. {
|
||||
path_builder.arc(origin, distance_to_elbow_TR, rad_R - angle, rad_T, true);
|
||||
}
|
||||
}
|
||||
|
||||
match mode {
|
||||
|
@ -514,18 +665,26 @@ impl<'a> PaintContext<'a> {
|
|||
|
||||
if radius.top_left != 0. {
|
||||
let origin = edge_TL + Point2D::new(-(border.left - radius.top_left).max(0.),
|
||||
radius.top_left);
|
||||
let distance_to_elbow = (radius.top_left - border.top).max(0.);
|
||||
radius.top_left);
|
||||
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);
|
||||
path_builder.arc(origin, radius.top_left, rad_TL, rad_T, false);
|
||||
if distance_to_elbow_TL != 0. {
|
||||
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 => {
|
||||
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_TR = edge_TL + dx(border.left);
|
||||
let edge_BR = edge_BL + dx(border.left);
|
||||
let edge_TR = box_TL + dx(border.left) + dy(border.top + distance_to_elbow_TL);
|
||||
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_BL = edge_BL + dy_if(radius.bottom_left == 0., border.bottom);
|
||||
|
@ -540,11 +699,20 @@ impl<'a> PaintContext<'a> {
|
|||
|
||||
if radius.top_left != 0. {
|
||||
let origin = edge_TL + Point2D::new(radius.top_left,
|
||||
-(border.top - radius.top_left).max(0.));
|
||||
let distance_to_elbow = (radius.top_left - border.left).max(0.);
|
||||
-(border.top - radius.top_left).max(0.));
|
||||
|
||||
path_builder.arc(origin, radius.top_left, rad_L, rad_TL, false);
|
||||
path_builder.arc(origin, distance_to_elbow, rad_TL, rad_L, true);
|
||||
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, 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 {
|
||||
|
@ -558,18 +726,28 @@ impl<'a> PaintContext<'a> {
|
|||
if radius.bottom_left != 0. {
|
||||
let origin = edge_BL +
|
||||
Point2D::new(radius.bottom_left,
|
||||
(border.bottom - radius.bottom_left).max(0.));
|
||||
let distance_to_elbow = (radius.bottom_left - border.left).max(0.);
|
||||
(border.bottom - radius.bottom_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);
|
||||
path_builder.arc(origin, radius.bottom_left, rad_BL, rad_L, false);
|
||||
if distance_to_elbow_BL != 0. {
|
||||
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 => {
|
||||
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_TL = edge_TR + dx(-border.right);
|
||||
let edge_BL = edge_BR + dx(-border.right);
|
||||
let edge_TL = box_TR + dx(-border.right) + dy(border.top + distance_to_elbow_TR);
|
||||
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_BR = edge_BR + dy_if(radius.bottom_right == 0., border.bottom);
|
||||
|
@ -585,10 +763,18 @@ impl<'a> PaintContext<'a> {
|
|||
if radius.top_right != 0. {
|
||||
let origin = edge_TR + Point2D::new(-radius.top_right,
|
||||
-(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);
|
||||
path_builder.arc(origin, radius.top_right, rad_TR, rad_R, false);
|
||||
if distance_to_elbow_TR != 0. {
|
||||
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 {
|
||||
|
@ -602,18 +788,28 @@ impl<'a> PaintContext<'a> {
|
|||
if radius.bottom_right != 0. {
|
||||
let origin = edge_BR +
|
||||
Point2D::new(-radius.bottom_right,
|
||||
(border.bottom - radius.bottom_right).max(0.));
|
||||
let distance_to_elbow = (radius.bottom_right - border.right).max(0.);
|
||||
(border.bottom - radius.bottom_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, distance_to_elbow, rad_BR, rad_R, true);
|
||||
path_builder.arc(origin, radius.bottom_right, rad_R, rad_R + angle, false);
|
||||
if distance_to_elbow_BR != 0. {
|
||||
path_builder.arc(origin, distance_to_elbow_BR, rad_R + angle, rad_R, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Direction::Bottom => {
|
||||
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_TL = edge_BL + dy(-border.bottom);
|
||||
let edge_TR = edge_BR + dy(-border.bottom);
|
||||
let edge_TL = box_BL + dy(-border.bottom) + dx(border.left + distance_to_elbow_BL);
|
||||
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_BL = edge_BL + dx_if(radius.bottom_left == 0., -border.left);
|
||||
|
@ -629,10 +825,20 @@ impl<'a> PaintContext<'a> {
|
|||
if radius.bottom_right != 0. {
|
||||
let origin = edge_BR + Point2D::new((border.right - radius.bottom_right).max(0.),
|
||||
-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);
|
||||
path_builder.arc(origin, radius.bottom_right, rad_BR, rad_B, false);
|
||||
if distance_to_elbow_BR != 0. {
|
||||
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 {
|
||||
|
@ -645,11 +851,21 @@ impl<'a> PaintContext<'a> {
|
|||
|
||||
if radius.bottom_left != 0. {
|
||||
let origin = edge_BL - Point2D::new((border.left - radius.bottom_left).max(0.),
|
||||
radius.bottom_left);
|
||||
let distance_to_elbow = (radius.bottom_left - border.bottom).max(0.);
|
||||
radius.bottom_left);
|
||||
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, distance_to_elbow, rad_BL, rad_B, true);
|
||||
path_builder.arc(origin, radius.bottom_left, rad_B, rad_L - angle, false);
|
||||
if distance_to_elbow_BL != 0. {
|
||||
path_builder.arc(origin, distance_to_elbow_BL, rad_L - angle, rad_B, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
vec!(
|
||||
"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> {
|
||||
vec!("Roboto".to_owned())
|
||||
}
|
||||
|
|
|
@ -33,11 +33,6 @@ pub struct FontTable {
|
|||
data: CFData,
|
||||
}
|
||||
|
||||
// Noncopyable.
|
||||
impl Drop for FontTable {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl FontTable {
|
||||
pub fn wrap(data: CFData) -> FontTable {
|
||||
FontTable { data: data }
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
* 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/. */
|
||||
|
||||
#[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};
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
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 font;
|
||||
pub mod font_context;
|
||||
|
@ -16,7 +16,7 @@ pub mod freetype {
|
|||
pub mod font_template;
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos {
|
||||
pub mod font;
|
||||
pub mod font_context;
|
||||
|
|
|
@ -58,17 +58,7 @@ impl GlyphEntry {
|
|||
starts_ligature,
|
||||
glyph_count);
|
||||
|
||||
let mut val = FLAG_NOT_MISSING;
|
||||
|
||||
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)
|
||||
GlyphEntry::new(glyph_count as u32)
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
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
|
||||
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.
|
||||
|
||||
static FLAG_CHAR_IS_SPACE: u32 = 0x10000000;
|
||||
// These two bits store some BREAK_TYPE_* flags
|
||||
static FLAG_CAN_BREAK_MASK: u32 = 0x60000000;
|
||||
static FLAG_CAN_BREAK_SHIFT: u32 = 29;
|
||||
static FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000;
|
||||
const FLAG_CHAR_IS_SPACE: u32 = 0x40000000;
|
||||
const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000;
|
||||
|
||||
// glyph advance; in Au's.
|
||||
static GLYPH_ADVANCE_MASK: u32 = 0x0FFF0000;
|
||||
static GLYPH_ADVANCE_SHIFT: u32 = 16;
|
||||
static GLYPH_ID_MASK: u32 = 0x0000FFFF;
|
||||
const GLYPH_ADVANCE_MASK: u32 = 0x3FFF0000;
|
||||
const GLYPH_ADVANCE_SHIFT: u32 = 16;
|
||||
const GLYPH_ID_MASK: u32 = 0x0000FFFF;
|
||||
|
||||
// Non-simple glyphs (more than one glyph per char; missing glyph,
|
||||
// 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
|
||||
// unicode char.
|
||||
|
||||
// The number of detailed glyphs for this char. If the char couldn't
|
||||
// be mapped to a glyph (!FLAG_NOT_MISSING), then this actually holds
|
||||
// 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;
|
||||
// The number of detailed glyphs for this char.
|
||||
const GLYPH_COUNT_MASK: u32 = 0x0000FFFF;
|
||||
|
||||
fn is_simple_glyph_id(id: GlyphId) -> bool {
|
||||
((id as u32) & GLYPH_ID_MASK) == id
|
||||
|
@ -164,7 +108,6 @@ type DetailedGlyphCount = u16;
|
|||
// Getters and setters for GlyphEntry. Setter methods are functional,
|
||||
// because GlyphEntry is immutable and only a u32 in size.
|
||||
impl GlyphEntry {
|
||||
// getter methods
|
||||
#[inline(always)]
|
||||
fn advance(&self) -> Au {
|
||||
Au(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32)
|
||||
|
@ -174,62 +117,20 @@ impl GlyphEntry {
|
|||
self.value & GLYPH_ID_MASK
|
||||
}
|
||||
|
||||
fn is_ligature_start(&self) -> bool {
|
||||
self.has_flag(!FLAG_NOT_LIGATURE_GROUP_START)
|
||||
}
|
||||
|
||||
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.
|
||||
/// 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 {
|
||||
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)]
|
||||
fn set_char_is_space(&self) -> GlyphEntry {
|
||||
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 {
|
||||
assert!(!self.is_simple());
|
||||
((self.value & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT) as u16
|
||||
(self.value & GLYPH_COUNT_MASK) as u16
|
||||
}
|
||||
|
||||
#[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(' ') {
|
||||
entry = entry.set_char_is_space()
|
||||
}
|
||||
|
@ -647,62 +545,11 @@ impl<'a> GlyphStore {
|
|||
.fold(Au(0), |advance, (_, glyph)| advance + glyph.advance())
|
||||
}
|
||||
|
||||
// getter methods
|
||||
pub fn char_is_space(&self, i: CharIndex) -> bool {
|
||||
assert!(i < self.char_len());
|
||||
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 {
|
||||
let mut spaces = 0;
|
||||
for index in range.each_index() {
|
||||
|
|
|
@ -576,13 +576,13 @@ extern fn glyph_h_advance_func(_: *mut hb_font_t,
|
|||
fn glyph_space_advance(font: *mut Font) -> f64 {
|
||||
let space_unicode = ' ';
|
||||
let space_glyph: hb_codepoint_t;
|
||||
match unsafe {(*font).glyph_index(space_unicode)} {
|
||||
match unsafe { (*font).glyph_index(space_unicode) } {
|
||||
Some(g) => {
|
||||
space_glyph = g as hb_codepoint_t;
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -570,7 +570,7 @@ pub struct BlockFlow {
|
|||
|
||||
bitflags! {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ impl PrivateLayoutData {
|
|||
|
||||
bitflags! {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,6 +313,10 @@ impl Flow for FlexFlow {
|
|||
&mut self.block_flow
|
||||
}
|
||||
|
||||
fn mark_as_root(&mut self) {
|
||||
self.block_flow.mark_as_root();
|
||||
}
|
||||
|
||||
fn bubble_inline_sizes(&mut self) {
|
||||
let _scope = layout_debug_scope!("flex::bubble_inline_sizes {:x}",
|
||||
self.block_flow.base.debug_id());
|
||||
|
|
|
@ -2309,10 +2309,10 @@ bitflags! {
|
|||
// Various flags we can use when splitting fragments. See
|
||||
// `calculate_split_position_using_breaking_strategy()`.
|
||||
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,
|
||||
#[doc="True if we should attempt to split at character boundaries if this split fails. \
|
||||
This is used to implement `overflow-wrap: break-word`."]
|
||||
#[doc = "True if we should attempt to split at character boundaries if this split fails. \
|
||||
This is used to implement `overflow-wrap: break-word`."]
|
||||
const RETRY_AT_CHARACTER_BOUNDARIES = 0x02,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ bitflags! {
|
|||
|
||||
bitflags! {
|
||||
flags SpecialRestyleDamage: u8 {
|
||||
#[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."]
|
||||
#[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."]
|
||||
const REFLOW_ENTIRE_DOCUMENT = 0x01,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,9 +183,9 @@ int_range_index! {
|
|||
|
||||
bitflags! {
|
||||
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,
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
use block::{BlockFlow, FloatNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput};
|
||||
use block::{BlockFlow, FloatNonReplaced, AbsoluteNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput};
|
||||
use block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
|
||||
use context::LayoutContext;
|
||||
use floats::FloatKind;
|
||||
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 model::MaybeAuto;
|
||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
|
||||
|
@ -242,6 +242,26 @@ impl TableWrapperFlow {
|
|||
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 {
|
||||
minimum_width_of_all_columns: minimum_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)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ extern crate util;
|
|||
extern crate url;
|
||||
extern crate style;
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate core_foundation;
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate io_surface;
|
||||
|
||||
pub mod compositor_msg;
|
||||
|
|
|
@ -2,49 +2,47 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
use 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 net_traits::ProgressMsg::{Payload, Done};
|
||||
use net_traits::hosts::replace_hosts;
|
||||
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 resource_task::{start_sending_opt, start_sending_sniffed_opt};
|
||||
use std::borrow::ToOwned;
|
||||
use std::boxed::FnBox;
|
||||
use std::collections::HashSet;
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::mpsc::{Sender, channel};
|
||||
use url::{Url, UrlParser};
|
||||
use util::opts;
|
||||
use util::resource_files::resources_dir_path;
|
||||
use util::task::spawn_named;
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
use std::boxed::FnBox;
|
||||
use uuid;
|
||||
|
||||
pub fn factory(resource_mgr_chan: IpcSender<ControlMsg>,
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
hsts_list: Arc<Mutex<HSTSList>>)
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>)
|
||||
-> Box<FnBox(LoadData, LoadConsumer, Arc<MIMEClassifier>) + Send> {
|
||||
box move |load_data, senders, classifier| {
|
||||
spawn_named("http_loader".to_owned(),
|
||||
move || load(load_data, senders, classifier, resource_mgr_chan, devtools_chan, hsts_list))
|
||||
box move |load_data: LoadData, senders, classifier| {
|
||||
spawn_named(format!("http_loader for {}", load_data.url.serialize()),
|
||||
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 {
|
||||
match url.domain() {
|
||||
Some(ref h) => {
|
||||
hsts_list.is_host_secure(h)
|
||||
},
|
||||
_ => false
|
||||
fn inner_url(url: &Url) -> Url {
|
||||
let inner_url = url.non_relative_scheme_data().unwrap();
|
||||
Url::parse(inner_url).unwrap()
|
||||
}
|
||||
|
||||
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,
|
||||
start_chan: LoadConsumer,
|
||||
classifier: Arc<MIMEClassifier>,
|
||||
resource_mgr_chan: IpcSender<ControlMsg>,
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
hsts_list: Arc<Mutex<HSTSList>>) {
|
||||
pub trait HttpResponse: Read {
|
||||
fn headers(&self) -> &Headers;
|
||||
fn status(&self) -> StatusCode;
|
||||
fn status_raw(&self) -> &RawStatus;
|
||||
|
||||
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
|
||||
// location for configuration. If you're reading this and such a
|
||||
// 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.
|
||||
let mut url = replace_hosts(&load_data.url);
|
||||
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
|
||||
// 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.
|
||||
let viewing_source = url.scheme == "view-source";
|
||||
if viewing_source {
|
||||
let inner_url = load_data.url.non_relative_scheme_data().unwrap();
|
||||
doc_url = Url::parse(inner_url).unwrap();
|
||||
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;
|
||||
}
|
||||
};
|
||||
url = inner_url(&load_data.url);
|
||||
doc_url = url.clone();
|
||||
}
|
||||
|
||||
// Loop to handle redirects.
|
||||
loop {
|
||||
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);
|
||||
url = secure_url(&url);
|
||||
}
|
||||
|
||||
if iters > max_redirects {
|
||||
send_error(url, "too many redirects".to_string(), start_chan);
|
||||
return;
|
||||
return Err(LoadError::MaxRedirects(url));
|
||||
}
|
||||
|
||||
match &*url.scheme {
|
||||
"http" | "https" => {}
|
||||
_ => {
|
||||
let s = format!("{} request, but we don't support that scheme", url.scheme);
|
||||
send_error(url, s, start_chan);
|
||||
return;
|
||||
}
|
||||
if &*url.scheme != "http" && &*url.scheme != "https" {
|
||||
return Err(LoadError::UnsupportedScheme(url));
|
||||
}
|
||||
|
||||
info!("requesting {}", url.serialize());
|
||||
|
||||
let ssl_err_string = "Some(OpenSslErrors([UnknownError { library: \"SSL routines\", \
|
||||
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
|
||||
// Ensure that the host header is set from the original url
|
||||
let host = Host {
|
||||
hostname: doc_url.serialize_host().unwrap(),
|
||||
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
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=216828 .
|
||||
// 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();
|
||||
combined_headers.extend(load_data.preserved_headers.iter());
|
||||
*req.headers_mut() = combined_headers;
|
||||
combined_headers
|
||||
} 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>() {
|
||||
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)),
|
||||
]);
|
||||
req.headers_mut().set(accept);
|
||||
}
|
||||
set_default_accept(&mut request_headers);
|
||||
set_default_accept_encoding(&mut request_headers);
|
||||
set_request_cookies(doc_url.clone(), &mut request_headers, &resource_mgr_chan);
|
||||
|
||||
let (tx, rx) = ipc::channel().unwrap();
|
||||
resource_mgr_chan.send(ControlMsg::GetCookiesForUrl(doc_url.clone(),
|
||||
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);
|
||||
}
|
||||
let mut req = try!(request_factory.create(url.clone(), method.clone()));
|
||||
*req.headers_mut() = request_headers;
|
||||
|
||||
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) {
|
||||
info!("{}", load_data.method);
|
||||
for header in req.headers().iter() {
|
||||
info!("{}", method);
|
||||
for header in req.headers_mut().iter() {
|
||||
info!(" - {}", header);
|
||||
}
|
||||
info!("{:?}", load_data.data);
|
||||
}
|
||||
|
||||
// Avoid automatically sending request body if a redirect has occurred.
|
||||
let writer = match load_data.data {
|
||||
Some(ref data) if iters == 1 => {
|
||||
req.headers_mut().set(ContentLength(data.len() as u64));
|
||||
let mut writer = match req.start() {
|
||||
Ok(w) => w,
|
||||
Err(e) => {
|
||||
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
|
||||
//
|
||||
// TODO - This is the wrong behaviour according to the RFC. However, I'm not
|
||||
// sure how much "correctness" vs. real-world is important in this case.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7231#section-6.4
|
||||
let is_redirected_request = iters != 1;
|
||||
let request_id = uuid::Uuid::new_v4().to_simple_string();
|
||||
if let Some(ref chan) = devtools_chan {
|
||||
let net_event = NetworkEvent::HttpRequest(load_data.url.clone(),
|
||||
load_data.method.clone(),
|
||||
load_data.headers.clone(),
|
||||
load_data.data.clone());
|
||||
chan.send(DevtoolsControlMsg::FromChrome(
|
||||
ChromeToDevtoolsControlMsg::NetworkEvent(request_id.clone(),
|
||||
net_event))).unwrap();
|
||||
}
|
||||
let response = match load_data.data {
|
||||
Some(ref data) if !is_redirected_request => {
|
||||
req.headers_mut().set(ContentLength(data.len() as u64));
|
||||
|
||||
let mut response = match writer.send() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
send_error(url, e.description().to_string(), start_chan);
|
||||
return;
|
||||
// TODO: Do this only if load_data has some pipeline_id, and send the pipeline_id
|
||||
// in the message
|
||||
send_request_to_devtools(
|
||||
devtools_chan.clone(), request_id.clone(), url.clone(),
|
||||
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) {
|
||||
for header in response.headers.iter() {
|
||||
for header in response.headers().iter() {
|
||||
info!(" - {}", header);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(cookies) = response.headers.get_raw("set-cookie") {
|
||||
for cookie in cookies {
|
||||
if let Ok(cookies) = String::from_utf8(cookie.clone()) {
|
||||
resource_mgr_chan.send(ControlMsg::SetCookiesForUrl(doc_url.clone(),
|
||||
cookies,
|
||||
CookieSource::HTTP)).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
set_cookies_from_response(doc_url.clone(), &response, &resource_mgr_chan);
|
||||
update_sts_list_from_response(&url, &response, &resource_mgr_chan);
|
||||
|
||||
if url.scheme == "https" {
|
||||
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
|
||||
};
|
||||
|
||||
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>() {
|
||||
// --- Loop if there's a redirect
|
||||
if response.status().class() == StatusClass::Redirection {
|
||||
match response.headers().get::<Location>() {
|
||||
Some(&Location(ref new_url)) => {
|
||||
// CORS (https://fetch.spec.whatwg.org/#http-fetch, status section, point 9, 10)
|
||||
match load_data.cors {
|
||||
Some(ref c) => {
|
||||
if c.preflight {
|
||||
// The preflight lied
|
||||
send_error(url,
|
||||
"Preflight fetch inconsistent with main fetch".to_string(),
|
||||
start_chan);
|
||||
return;
|
||||
return Err(
|
||||
LoadError::Cors(
|
||||
url,
|
||||
"Preflight fetch inconsistent with main fetch".to_string()));
|
||||
} else {
|
||||
// XXXManishearth There are some CORS-related steps here,
|
||||
// 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) {
|
||||
Ok(u) => u,
|
||||
Err(e) => {
|
||||
send_error(doc_url, e.to_string(), start_chan);
|
||||
return;
|
||||
return Err(LoadError::InvalidRedirect(doc_url, e.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
info!("redirecting to {}", new_doc_url);
|
||||
url = replace_hosts(&new_doc_url);
|
||||
doc_url = new_doc_url;
|
||||
|
||||
// According to https://tools.ietf.org/html/rfc7231#section-6.4.2,
|
||||
// historically UAs have rewritten POST->GET on 301 and 302 responses.
|
||||
if load_data.method == Method::Post &&
|
||||
(response.status == StatusCode::MovedPermanently ||
|
||||
response.status == StatusCode::Found) {
|
||||
load_data.method = Method::Get;
|
||||
if method == Method::Post &&
|
||||
(response.status() == StatusCode::MovedPermanently ||
|
||||
response.status() == StatusCode::Found) {
|
||||
method = Method::Get;
|
||||
}
|
||||
|
||||
if redirected_to.contains(&doc_url) {
|
||||
send_error(doc_url, "redirect loop".to_string(), start_chan);
|
||||
return;
|
||||
if redirected_to.contains(&url) {
|
||||
return Err(LoadError::InvalidRedirect(doc_url, "redirect loop".to_string()));
|
||||
}
|
||||
|
||||
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 {
|
||||
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() {
|
||||
Some(&ContentType(ref mime)) => Some(mime),
|
||||
None => None
|
||||
|
@ -392,56 +621,16 @@ reason: \"certificate verify failed\" }]))";
|
|||
metadata.headers = Some(adjusted_headers);
|
||||
metadata.status = Some(response.status_raw().clone());
|
||||
|
||||
let mut encoding_str: Option<String> = None;
|
||||
//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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Tell devtools that we got a response
|
||||
// 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
|
||||
if let Some(ref chan) = devtools_chan {
|
||||
let net_event_response =
|
||||
NetworkEvent::HttpResponse(metadata.headers.clone(),
|
||||
metadata.status.clone(),
|
||||
None);
|
||||
chan.send(DevtoolsControlMsg::FromChrome(
|
||||
ChromeToDevtoolsControlMsg::NetworkEvent(request_id,
|
||||
net_event_response))).unwrap();
|
||||
}
|
||||
// TODO: Send this message even when the load fails?
|
||||
send_response_to_devtools(
|
||||
devtools_chan, request_id,
|
||||
metadata.headers.clone(), metadata.status.clone()
|
||||
);
|
||||
|
||||
match encoding_str {
|
||||
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;
|
||||
return StreamedResponse::from_http_response(response, metadata)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
use std::cmp::max;
|
||||
|
||||
pub struct MIMEClassifier {
|
||||
image_classifier: GroupedClassifier,
|
||||
|
@ -24,51 +23,34 @@ impl MIMEClassifier {
|
|||
data: &[u8]) -> Option<(String, String)> {
|
||||
|
||||
match *supplied_type {
|
||||
None => {
|
||||
return self.sniff_unknown_type(!no_sniff, data);
|
||||
}
|
||||
None => self.sniff_unknown_type(!no_sniff, data),
|
||||
Some((ref media_type, ref media_subtype)) => {
|
||||
match (&**media_type, &**media_subtype) {
|
||||
("unknown", "unknown") | ("application", "unknown") | ("*", "*") => {
|
||||
return self.sniff_unknown_type(!no_sniff, data);
|
||||
}
|
||||
("unknown", "unknown") |
|
||||
("application", "unknown") |
|
||||
("*", "*") => self.sniff_unknown_type(!no_sniff, data),
|
||||
_ => {
|
||||
if no_sniff {
|
||||
return supplied_type.clone();
|
||||
}
|
||||
if check_for_apache_bug {
|
||||
return self.sniff_text_or_data(data);
|
||||
}
|
||||
|
||||
if MIMEClassifier::is_xml(media_type, media_subtype) {
|
||||
return supplied_type.clone();
|
||||
}
|
||||
//Inplied in section 7.3, but flow is not clear
|
||||
if MIMEClassifier::is_html(media_type, media_subtype) {
|
||||
return self.feeds_classifier
|
||||
.classify(data)
|
||||
.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);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
supplied_type.clone()
|
||||
} else if check_for_apache_bug {
|
||||
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) {
|
||||
//Implied in section 7.3, but flow is not clear
|
||||
self.feeds_classifier.classify(data).or(supplied_type.clone())
|
||||
} else {
|
||||
match (&**media_type, &**media_subtype) {
|
||||
("image", _) => self.image_classifier.classify(data),
|
||||
("audio", _) | ("video", _) | ("application", "ogg") =>
|
||||
self.audio_video_classifer.classify(data),
|
||||
_ => None
|
||||
}.or(supplied_type.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return supplied_type.clone();
|
||||
}
|
||||
|
||||
pub fn new() -> MIMEClassifier {
|
||||
|
@ -99,13 +81,15 @@ impl MIMEClassifier {
|
|||
fn sniff_text_or_data(&self, data: &[u8]) -> Option<(String, String)> {
|
||||
self.binary_or_plaintext.classify(data)
|
||||
}
|
||||
|
||||
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)..];
|
||||
match (tp, sub_tp, suffix) {
|
||||
(_, _, "+xml") | ("application", "xml",_) | ("text", "xml",_) => {true}
|
||||
_ => {false}
|
||||
}
|
||||
sub_tp.ends_with("+xml") ||
|
||||
match (tp, sub_tp) {
|
||||
("application", "xml") | ("text", "xml") => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_html(tp: &str, sub_tp: &str) -> bool {
|
||||
tp == "text" && sub_tp == "html"
|
||||
}
|
||||
|
@ -141,13 +125,11 @@ impl <'a, T: Iterator<Item=&'a u8> + Clone> Matches for T {
|
|||
// Side effects
|
||||
// moves the iterator when match is found
|
||||
fn matches(&mut self, matches: &[u8]) -> bool {
|
||||
for (byte_a, byte_b) in self.clone().take(matches.len()).zip(matches) {
|
||||
if byte_a != byte_b {
|
||||
return false;
|
||||
}
|
||||
let result = self.clone().zip(matches).all(|(s, m)| *s == *m);
|
||||
if result {
|
||||
self.nth(matches.len());
|
||||
}
|
||||
self.nth(matches.len());
|
||||
true
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,36 +137,27 @@ struct ByteMatcher {
|
|||
pattern: &'static [u8],
|
||||
mask: &'static [u8],
|
||||
leading_ignore: &'static [u8],
|
||||
content_type: (&'static str,&'static str)
|
||||
content_type: (&'static str, &'static str)
|
||||
}
|
||||
|
||||
impl ByteMatcher {
|
||||
fn matches(&self, data: &[u8]) -> Option<usize> {
|
||||
|
||||
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 {
|
||||
fn classify(&self, data: &[u8]) -> Option<(String, String)> {
|
||||
let pattern = self.matcher.matches(data);
|
||||
let pattern_matches = pattern.map(|j| j < data.len() && (data[j] == b' ' || data[j] == b'>'));
|
||||
if pattern_matches.unwrap_or(false) {
|
||||
Some((self.matcher.content_type.0.to_owned(),
|
||||
self.matcher.content_type.1.to_owned()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.matcher.matches(data).and_then(|j|
|
||||
if j < data.len() && (data[j] == b' ' || data[j] == b'>') {
|
||||
Some((self.matcher.content_type.0.to_owned(),
|
||||
self.matcher.content_type.1.to_owned()))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
pub struct Mp4Matcher;
|
||||
|
@ -219,48 +191,21 @@ impl Mp4Matcher {
|
|||
if data.len() < 12 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let box_size = ((data[0] as u32) << 3 | (data[1] as u32) << 2 |
|
||||
(data[2] as u32) << 1 | (data[3] as u32)) as usize;
|
||||
if (data.len() < box_size) || (box_size % 4 != 0) {
|
||||
return false;
|
||||
}
|
||||
//TODO replace with iterators
|
||||
|
||||
let ftyp = [0x66, 0x74, 0x79, 0x70];
|
||||
let mp4 = [0x6D, 0x70, 0x34];
|
||||
|
||||
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;
|
||||
if !data[4..].starts_with(&ftyp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut bytes_read: usize = 16;
|
||||
|
||||
while bytes_read < box_size {
|
||||
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
|
||||
let mp4 = [0x6D, 0x70, 0x34];
|
||||
data[8..].starts_with(&mp4) ||
|
||||
data[16..box_size].chunks(4).any(|chunk| chunk.starts_with(&mp4))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -278,27 +223,24 @@ struct BinaryOrPlaintextClassifier;
|
|||
|
||||
impl BinaryOrPlaintextClassifier {
|
||||
fn classify_impl(&self, data: &[u8]) -> (&'static str, &'static str) {
|
||||
if (data.len() >= 2 &&
|
||||
((data[0] == 0xFFu8 && data[1] == 0xFEu8) ||
|
||||
(data[0] == 0xFEu8 && data[1] == 0xFFu8))) ||
|
||||
(data.len() >= 3 && data[0] == 0xEFu8 && data[1] == 0xBBu8 && data[2] == 0xBFu8)
|
||||
if data == &[0xFFu8, 0xFEu8] ||
|
||||
data == &[0xFEu8, 0xFFu8] ||
|
||||
data.starts_with(&[0xEFu8, 0xBBu8, 0xBFu8])
|
||||
{
|
||||
("text", "plain")
|
||||
}
|
||||
else if data.len() >= 1 && data.iter().any(|&x| x <= 0x08u8 ||
|
||||
x == 0x0Bu8 ||
|
||||
(x >= 0x0Eu8 && x <= 0x1Au8) ||
|
||||
(x >= 0x1Cu8 && x <= 0x1Fu8)) {
|
||||
} else if data.iter().any(|&x| x <= 0x08u8 ||
|
||||
x == 0x0Bu8 ||
|
||||
(x >= 0x0Eu8 && x <= 0x1Au8) ||
|
||||
(x >= 0x1Cu8 && x <= 0x1Fu8)) {
|
||||
("application", "octet-stream")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
("text", "plain")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl MIMEChecker for BinaryOrPlaintextClassifier {
|
||||
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 {
|
||||
|
@ -358,7 +300,6 @@ impl GroupedClassifier {
|
|||
box ByteMatcher::application_pdf()
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
fn plaintext_classifier() -> 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;
|
||||
impl FeedsClassifier {
|
||||
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
|
||||
if length < 3 {
|
||||
if data.len() < 3 {
|
||||
return None;
|
||||
}
|
||||
|
||||
// eat the first three bytes if they are equal to UTF-8 BOM
|
||||
data_iterator.matches(utf8_bom);
|
||||
let mut matcher = data.iter();
|
||||
|
||||
// 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
|
||||
// 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"?") {
|
||||
// eat until ?>
|
||||
while !data_iterator.matches(b"?>") {
|
||||
if data_iterator.next().is_none() {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
} else if data_iterator.matches(b"!--") {
|
||||
// eat until -->
|
||||
while !data_iterator.matches(b"-->") {
|
||||
if data_iterator.next().is_none() {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
} else if data_iterator.matches(b"!") {
|
||||
data_iterator.find(|&data_iterator| *data_iterator == b'>');
|
||||
} else if data_iterator.matches(b"rss") {
|
||||
if matcher.find(|&x| *x == b'<').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">")) {
|
||||
Match::StartAndEnd => continue,
|
||||
Match::DidNotMatch => {},
|
||||
Match::Start => return None
|
||||
}
|
||||
|
||||
if matcher.matches(b"rss") {
|
||||
return Some(("application", "rss+xml"));
|
||||
} else if data_iterator.matches(b"feed") {
|
||||
}
|
||||
if matcher.matches(b"feed") {
|
||||
return Some(("application", "atom+xml"));
|
||||
} else if data_iterator.matches(b"rdf: RDF") {
|
||||
while !data_iterator.next().is_none() {
|
||||
if data_iterator.matches(b"http: //purl.org/rss/1.0/") {
|
||||
while !data_iterator.next().is_none() {
|
||||
if data_iterator.matches(b"http: //www.w3.org/1999/02/22-rdf-syntax-ns#") {
|
||||
return Some(("application", "rss+xml"));
|
||||
}
|
||||
}
|
||||
} else if data_iterator.matches(b"http: //www.w3.org/1999/02/22-rdf-syntax-ns#") {
|
||||
while !data_iterator.next().is_none() {
|
||||
if data_iterator.matches(b"http: //purl.org/rss/1.0/") {
|
||||
return Some(("application", "rss+xml"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if matcher.matches(b"rdf: RDF") {
|
||||
while matcher.next().is_some() {
|
||||
match eats_until(&mut matcher,
|
||||
b"http: //purl.org/rss/1.0/",
|
||||
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#",
|
||||
b"http: //purl.org/rss/1.0/")) {
|
||||
Match::StartAndEnd => return Some(("application", "rss+xml")),
|
||||
Match::DidNotMatch => {},
|
||||
Match::Start => return None
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
|||
use std::borrow::ToOwned;
|
||||
use std::boxed::FnBox;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
|
||||
pub enum ProgressSender {
|
||||
|
@ -161,23 +160,26 @@ impl ResourceChannelManager {
|
|||
fn start(&mut self) {
|
||||
loop {
|
||||
match self.from_client.recv().unwrap() {
|
||||
ControlMsg::Load(load_data, consumer) => {
|
||||
self.resource_manager.load(load_data, consumer)
|
||||
}
|
||||
ControlMsg::SetCookiesForUrl(request, cookie_list, source) => {
|
||||
self.resource_manager.set_cookies_for_url(request, cookie_list, source)
|
||||
}
|
||||
ControlMsg::GetCookiesForUrl(url, consumer, source) => {
|
||||
consumer.send(self.resource_manager.cookie_storage.cookies_for_url(&url, source)).unwrap();
|
||||
}
|
||||
ControlMsg::SetHSTSEntryForHost(host, include_subdomains, max_age) => {
|
||||
if let Some(entry) = HSTSEntry::new(host, include_subdomains, Some(max_age)) {
|
||||
self.resource_manager.add_hsts_entry(entry)
|
||||
}
|
||||
}
|
||||
ControlMsg::Exit => {
|
||||
break
|
||||
}
|
||||
ControlMsg::Load(load_data, consumer) => {
|
||||
self.resource_manager.load(load_data, consumer)
|
||||
}
|
||||
ControlMsg::SetCookiesForUrl(request, cookie_list, source) => {
|
||||
self.resource_manager.set_cookies_for_url(request, cookie_list, source)
|
||||
}
|
||||
ControlMsg::GetCookiesForUrl(url, consumer, source) => {
|
||||
consumer.send(self.resource_manager.cookie_storage.cookies_for_url(&url, source)).unwrap();
|
||||
}
|
||||
ControlMsg::SetHSTSEntryForHost(host, include_subdomains, max_age) => {
|
||||
if let Some(entry) = HSTSEntry::new(host, include_subdomains, Some(max_age)) {
|
||||
self.resource_manager.add_hsts_entry(entry)
|
||||
}
|
||||
}
|
||||
ControlMsg::GetHostMustBeSecured(host, consumer) => {
|
||||
consumer.send(self.resource_manager.is_host_sts(&*host)).unwrap();
|
||||
}
|
||||
ControlMsg::Exit => {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +191,7 @@ pub struct ResourceManager {
|
|||
resource_task: IpcSender<ControlMsg>,
|
||||
mime_classifier: Arc<MIMEClassifier>,
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
hsts_list: Arc<Mutex<HSTSList>>
|
||||
hsts_list: HSTSList
|
||||
}
|
||||
|
||||
impl ResourceManager {
|
||||
|
@ -203,7 +205,7 @@ impl ResourceManager {
|
|||
resource_task: resource_task,
|
||||
mime_classifier: Arc::new(MIMEClassifier::new()),
|
||||
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) {
|
||||
self.hsts_list.lock().unwrap().push(entry);
|
||||
self.hsts_list.push(entry);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -241,7 +243,7 @@ impl ResourceManager {
|
|||
let loader = match &*load_data.url.scheme {
|
||||
"file" => from_factory(file_loader::factory),
|
||||
"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),
|
||||
"about" => from_factory(about_loader::factory),
|
||||
_ => {
|
||||
|
|
|
@ -161,6 +161,7 @@ pub enum ControlMsg {
|
|||
GetCookiesForUrl(Url, IpcSender<Option<String>>, CookieSource),
|
||||
/// Store a domain's STS information
|
||||
SetHSTSEntryForHost(String, IncludeSubdomains, u64),
|
||||
GetHostMustBeSecured(String, IpcSender<bool>),
|
||||
Exit
|
||||
}
|
||||
|
||||
|
|
|
@ -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, #[privatize]));
|
||||
item2.attrs.push(quote_attr!(cx, #[derive(JSTraceable)]));
|
||||
item2.attrs.push(quote_attr!(cx, #[derive(HeapSizeOf)]));
|
||||
|
||||
// The following attributes are only for internal usage
|
||||
item2.attrs.push(quote_attr!(cx, #[_generate_reflector]));
|
||||
|
|
|
@ -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)
|
||||
pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> {
|
||||
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.
|
||||
// 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
|
||||
// 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) {
|
||||
match seg.last() {
|
||||
Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => {
|
||||
Some(&PathSegment { parameters: AngleBracketedParameters(ref a), .. }) => {
|
||||
Some(&a.types)
|
||||
}
|
||||
_ => None
|
||||
|
|
|
@ -13,9 +13,9 @@ extern crate ipc_channel;
|
|||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate profile_traits;
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
extern crate regex;
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
extern crate task_info;
|
||||
extern crate time as std_time;
|
||||
extern crate util;
|
||||
|
|
|
@ -368,7 +368,7 @@ mod system_reporter {
|
|||
use std::mem::size_of;
|
||||
use std::ptr::null_mut;
|
||||
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};
|
||||
|
||||
/// Collects global measurements from the OS and heap allocators.
|
||||
|
@ -418,12 +418,12 @@ mod system_reporter {
|
|||
request.reports_channel.send(reports);
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
extern {
|
||||
fn mallinfo() -> struct_mallinfo;
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
#[repr(C)]
|
||||
pub struct struct_mallinfo {
|
||||
arena: c_int,
|
||||
|
@ -438,7 +438,7 @@ mod system_reporter {
|
|||
keepcost: c_int,
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_system_heap_allocated() -> Option<usize> {
|
||||
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> {
|
||||
None
|
||||
}
|
||||
|
@ -507,14 +507,14 @@ mod system_reporter {
|
|||
($e:expr) => (match $e { Some(e) => e, None => return None })
|
||||
);
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn page_size() -> usize {
|
||||
unsafe {
|
||||
::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> {
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
@ -527,37 +527,37 @@ mod system_reporter {
|
|||
Some(npages * page_size())
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_vsize() -> Option<usize> {
|
||||
get_proc_self_statm_field(0)
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_resident() -> Option<usize> {
|
||||
get_proc_self_statm_field(1)
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_vsize() -> Option<usize> {
|
||||
virtual_size()
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn get_resident() -> Option<usize> {
|
||||
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> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os="linux", target_os = "macos")))]
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
|
||||
fn get_resident() -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_resident_segments() -> Vec<(String, usize)> {
|
||||
use regex::Regex;
|
||||
use std::collections::HashMap;
|
||||
|
@ -658,7 +658,7 @@ mod system_reporter {
|
|||
segs
|
||||
}
|
||||
|
||||
#[cfg(not(target_os="linux"))]
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn get_resident_segments() -> Vec<(String, usize)> {
|
||||
vec![]
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ features = ["query_encoding", "serde_serialization"]
|
|||
[dependencies.offscreen_gl_context]
|
||||
git = "https://github.com/ecoal95/rust-offscreen-rendering-context"
|
||||
|
||||
[dependencies.angle]
|
||||
git = "https://github.com/ecoal95/angle"
|
||||
branch = "servo"
|
||||
|
||||
[dependencies.cssparser]
|
||||
version = "0.3"
|
||||
features = [ "serde-serialization" ]
|
||||
|
|
|
@ -13,9 +13,7 @@ use dom::bindings::conversions::FromJSValConvertible;
|
|||
use dom::bindings::conversions::jsstring_to_str;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::document::DocumentHelpers;
|
||||
use dom::node::{Node, NodeHelpers};
|
||||
use dom::window::{WindowHelpers, ScriptHelpers};
|
||||
use dom::node::Node;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use js::jsapi::{ObjectClassName, RootedObject, RootedValue};
|
||||
use js::jsval::UndefinedValue;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
|
||||
use dom::element::{Element, ActivationElementHelpers};
|
||||
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
|
||||
use dom::element::Element;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::mouseevent::MouseEvent;
|
||||
use dom::node::window_from_node;
|
||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::global::GlobalRef;
|
|||
use dom::bindings::js::{JS, MutNullableHeap};
|
||||
use dom::bindings::js::{Root, RootedReference, LayoutJS};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::element::{Element, AttributeHandlers};
|
||||
use dom::element::Element;
|
||||
use dom::virtualmethods::vtable_for;
|
||||
use dom::window::Window;
|
||||
|
||||
|
@ -111,7 +111,6 @@ impl Deref for AttrValue {
|
|||
|
||||
// https://dom.spec.whatwg.org/#interface-attr
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Attr {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn LocalName(self) -> DOMString {
|
||||
fn LocalName(&self) -> DOMString {
|
||||
(**self.local_name()).to_owned()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-value
|
||||
fn Value(self) -> DOMString {
|
||||
fn Value(&self) -> DOMString {
|
||||
(**self.value()).to_owned()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-value
|
||||
fn SetValue(self, value: DOMString) {
|
||||
fn SetValue(&self, value: DOMString) {
|
||||
match self.owner() {
|
||||
None => *self.value.borrow_mut() = AttrValue::String(value),
|
||||
Some(owner) => {
|
||||
|
@ -186,32 +185,32 @@ impl<'a> AttrMethods for &'a Attr {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-textcontent
|
||||
fn TextContent(self) -> DOMString {
|
||||
fn TextContent(&self) -> DOMString {
|
||||
self.Value()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-textcontent
|
||||
fn SetTextContent(self, value: DOMString) {
|
||||
fn SetTextContent(&self, value: DOMString) {
|
||||
self.SetValue(value)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-nodevalue
|
||||
fn NodeValue(self) -> DOMString {
|
||||
fn NodeValue(&self) -> DOMString {
|
||||
self.Value()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-nodevalue
|
||||
fn SetNodeValue(self, value: DOMString) {
|
||||
fn SetNodeValue(&self, value: DOMString) {
|
||||
self.SetValue(value)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-name
|
||||
fn Name(self) -> DOMString {
|
||||
fn Name(&self) -> DOMString {
|
||||
(*self.name).to_owned()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-namespaceuri
|
||||
fn GetNamespaceURI(self) -> Option<DOMString> {
|
||||
fn GetNamespaceURI(&self) -> Option<DOMString> {
|
||||
let Namespace(ref atom) = self.namespace;
|
||||
match &**atom {
|
||||
"" => None,
|
||||
|
@ -220,32 +219,24 @@ impl<'a> AttrMethods for &'a Attr {
|
|||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-ownerelement
|
||||
fn GetOwnerElement(self) -> Option<Root<Element>> {
|
||||
fn GetOwnerElement(&self) -> Option<Root<Element>> {
|
||||
self.owner()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-attr-specified
|
||||
fn Specified(self) -> bool {
|
||||
fn Specified(&self) -> bool {
|
||||
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 {
|
||||
fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
|
||||
impl Attr {
|
||||
pub fn set_value(&self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
|
||||
assert!(Some(owner) == self.owner().r());
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
fn local_name(self) -> &'a Atom {
|
||||
pub fn local_name(&self) -> &Atom {
|
||||
&self.local_name
|
||||
}
|
||||
|
||||
/// Sets the owner element. Should be called after the attribute is added
|
||||
/// or removed from its older parent.
|
||||
fn set_owner(self, owner: Option<&Element>) {
|
||||
pub fn set_owner(&self, owner: Option<&Element>) {
|
||||
let ref ns = self.namespace;
|
||||
match (self.owner().r(), owner) {
|
||||
(None, Some(new)) => {
|
||||
|
@ -290,11 +281,11 @@ impl<'a> AttrHelpers<'a> for &'a Attr {
|
|||
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)
|
||||
}
|
||||
|
||||
fn summarize(self) -> AttrInfo {
|
||||
pub fn summarize(&self) -> AttrInfo {
|
||||
let Namespace(ref ns) = self.namespace;
|
||||
AttrInfo {
|
||||
namespace: (**ns).to_owned(),
|
||||
|
|
|
@ -339,7 +339,7 @@ class CGMethodCall(CGThing):
|
|||
code = (
|
||||
"if argc < %d {\n"
|
||||
" throw_type_error(cx, \"Not enough arguments to %s.\");\n"
|
||||
" return 0;\n"
|
||||
" return JSFalse;\n"
|
||||
"}" % (requiredArgs, methodName))
|
||||
self.cgRoot.prepend(
|
||||
CGWrapper(CGGeneric(code), pre="\n", post="\n"))
|
||||
|
@ -512,11 +512,11 @@ class CGMethodCall(CGThing):
|
|||
CGSwitch("argcount",
|
||||
argCountCases,
|
||||
CGGeneric("throw_type_error(cx, \"Not enough arguments to %s.\");\n"
|
||||
"return 0;" % methodName)))
|
||||
"return JSFalse;" % methodName)))
|
||||
# XXXjdm Avoid unreachable statement warnings
|
||||
# overloadCGThings.append(
|
||||
# CGGeneric('panic!("We have an always-returning default case");\n'
|
||||
# 'return 0;'))
|
||||
# 'return JSFalse;'))
|
||||
self.cgRoot = CGWrapper(CGList(overloadCGThings, "\n"),
|
||||
pre="\n")
|
||||
|
||||
|
@ -888,7 +888,11 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if invalidEnumValueFatal:
|
||||
handleInvalidEnumValueCode = exceptionCode
|
||||
else:
|
||||
handleInvalidEnumValueCode = "return 1;"
|
||||
handleInvalidEnumValueCode = "return JSTrue;"
|
||||
|
||||
transmute = "mem::transmute(index)"
|
||||
if isMember == 'Dictionary':
|
||||
transmute = 'unsafe { ' + transmute + ' }'
|
||||
|
||||
template = (
|
||||
"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(Some(index)) => {\n"
|
||||
" //XXXjdm need some range checks up in here.\n"
|
||||
" unsafe { mem::transmute(index) }\n"
|
||||
" %(transmute)s\n"
|
||||
" },\n"
|
||||
"}" % {"values": enum + "Values::strings",
|
||||
"exceptionCode": exceptionCode,
|
||||
"transmute": transmute,
|
||||
"handleInvalidEnumValueCode": handleInvalidEnumValueCode})
|
||||
|
||||
if defaultValue is not None:
|
||||
|
@ -1012,7 +1017,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
declType = CGGeneric(typeName)
|
||||
template = ("match %s::new(cx, ${val}) {\n"
|
||||
" Ok(dictionary) => dictionary,\n"
|
||||
" Err(_) => return 0,\n"
|
||||
" Err(_) => return JSFalse,\n"
|
||||
"}" % typeName)
|
||||
|
||||
return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName))
|
||||
|
@ -1037,7 +1042,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
conversionBehavior = "()"
|
||||
|
||||
if failureCode is None:
|
||||
failureCode = 'return 0'
|
||||
failureCode = 'return JSFalse'
|
||||
|
||||
declType = CGGeneric(builtinNames[type.tag()])
|
||||
if type.nullable():
|
||||
|
@ -1216,7 +1221,7 @@ class CGArgumentConverter(CGThing):
|
|||
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.
|
||||
|
||||
|
@ -1472,6 +1477,7 @@ class AttrDefiner(PropertyDefiner):
|
|||
def __init__(self, descriptor, name, static):
|
||||
PropertyDefiner.__init__(self, descriptor, name)
|
||||
self.name = name
|
||||
self.descriptor = descriptor
|
||||
self.regular = [
|
||||
m
|
||||
for m in descriptor.interface.members
|
||||
|
@ -1488,14 +1494,14 @@ class AttrDefiner(PropertyDefiner):
|
|||
|
||||
def getter(attr):
|
||||
if self.static:
|
||||
accessor = 'get_' + attr.identifier.name
|
||||
accessor = 'get_' + self.descriptor.internalNameFor(attr.identifier.name)
|
||||
jitinfo = "0 as *const JSJitInfo"
|
||||
else:
|
||||
if attr.hasLenientThis():
|
||||
accessor = "generic_lenient_getter"
|
||||
else:
|
||||
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 }"
|
||||
% {"info": jitinfo,
|
||||
|
@ -1506,14 +1512,14 @@ class AttrDefiner(PropertyDefiner):
|
|||
return "JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }"
|
||||
|
||||
if self.static:
|
||||
accessor = 'set_' + attr.identifier.name
|
||||
accessor = 'set_' + self.descriptor.internalNameFor(attr.identifier.name)
|
||||
jitinfo = "0 as *const JSJitInfo"
|
||||
else:
|
||||
if attr.hasLenientThis():
|
||||
accessor = "generic_lenient_setter"
|
||||
else:
|
||||
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 }"
|
||||
% {"info": jitinfo,
|
||||
|
@ -1620,19 +1626,11 @@ class CGImports(CGWrapper):
|
|||
"""
|
||||
if ignored_warnings is None:
|
||||
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_upper_case_globals',
|
||||
'unused_parens',
|
||||
'unused_imports',
|
||||
'unused_variables',
|
||||
'unused_unsafe',
|
||||
'unused_mut',
|
||||
'unused_assignments',
|
||||
'dead_code',
|
||||
]
|
||||
|
||||
def componentTypes(type):
|
||||
|
@ -2049,7 +2047,7 @@ class CGAbstractMethod(CGThing):
|
|||
"""
|
||||
def __init__(self, descriptor, name, returnType, args, inline=False,
|
||||
alwaysInline=False, extern=False, pub=False, templateArgs=None,
|
||||
unsafe=True):
|
||||
unsafe=False):
|
||||
CGThing.__init__(self)
|
||||
self.descriptor = descriptor
|
||||
self.name = name
|
||||
|
@ -2111,7 +2109,7 @@ class CGAbstractMethod(CGThing):
|
|||
|
||||
|
||||
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:
|
||||
assert not descriptor.isGlobal()
|
||||
create += """
|
||||
|
@ -2160,12 +2158,13 @@ class CGWrapMethod(CGAbstractMethod):
|
|||
assert not descriptor.interface.isCallback()
|
||||
if not descriptor.isGlobal():
|
||||
args = [Argument('*mut JSContext', 'cx'), Argument('GlobalRef', 'scope'),
|
||||
Argument("Box<%s>" % descriptor.concreteType, 'object', mutable=True)]
|
||||
Argument("Box<%s>" % descriptor.concreteType, 'object')]
|
||||
else:
|
||||
args = [Argument('*mut JSContext', 'cx'),
|
||||
Argument("Box<%s>" % descriptor.concreteType, 'object', mutable=True)]
|
||||
Argument("Box<%s>" % descriptor.concreteType, 'object')]
|
||||
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):
|
||||
if not self.descriptor.isGlobal():
|
||||
|
@ -2309,6 +2308,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
def definition_body(self):
|
||||
protoChain = self.descriptor.prototypeChain
|
||||
if len(protoChain) == 1:
|
||||
self.unsafe = True
|
||||
getParentProto = "parent_proto.ptr = JS_GetObjectPrototype(cx, global)"
|
||||
else:
|
||||
parentProtoName = self.descriptor.prototypeChain[-2]
|
||||
|
@ -2382,7 +2382,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
|||
Argument('HandleObject', 'receiver'),
|
||||
Argument('MutableHandleObject', 'rval')]
|
||||
CGAbstractMethod.__init__(self, descriptor, name,
|
||||
'void', args, pub=pub)
|
||||
'void', args, pub=pub, unsafe=True)
|
||||
self.id = idPrefix + "ID::" + self.descriptor.name
|
||||
|
||||
def definition_body(self):
|
||||
|
@ -2452,7 +2452,9 @@ class CGDefineProxyHandler(CGAbstractMethod):
|
|||
"""
|
||||
def __init__(self, descriptor):
|
||||
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):
|
||||
return CGAbstractMethod.define(self)
|
||||
|
@ -2778,7 +2780,7 @@ class CGSetterCall(CGPerSignatureCall):
|
|||
|
||||
def wrap_return_value(self):
|
||||
# We have no return value
|
||||
return "\nreturn 1;"
|
||||
return "\nreturn JSTrue;"
|
||||
|
||||
def getArgc(self):
|
||||
return "1"
|
||||
|
@ -2835,7 +2837,10 @@ class CGSpecializedMethod(CGAbstractExternMethod):
|
|||
@staticmethod
|
||||
def makeNativeName(descriptor, method):
|
||||
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):
|
||||
|
@ -2850,7 +2855,7 @@ class CGStaticMethod(CGAbstractStaticBindingMethod):
|
|||
def generate_code(self):
|
||||
nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
|
||||
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)
|
||||
return CGList([setupArgs, call])
|
||||
|
||||
|
@ -2862,7 +2867,7 @@ class CGSpecializedGetter(CGAbstractExternMethod):
|
|||
"""
|
||||
def __init__(self, descriptor, attr):
|
||||
self.attr = attr
|
||||
name = 'get_' + attr.identifier.name
|
||||
name = 'get_' + descriptor.internalNameFor(attr.identifier.name)
|
||||
args = [Argument('*mut JSContext', 'cx'),
|
||||
Argument('HandleObject', '_obj'),
|
||||
Argument('*const %s' % descriptor.concreteType, 'this'),
|
||||
|
@ -2880,7 +2885,10 @@ class CGSpecializedGetter(CGAbstractExternMethod):
|
|||
@staticmethod
|
||||
def makeNativeName(descriptor, attr):
|
||||
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
|
||||
descriptor.getExtendedAttributes(attr, getter=True))
|
||||
if attr.type.nullable() or not infallible:
|
||||
|
@ -2901,7 +2909,7 @@ class CGStaticGetter(CGAbstractStaticBindingMethod):
|
|||
def generate_code(self):
|
||||
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
|
||||
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,
|
||||
self.attr)
|
||||
return CGList([setupArgs, call])
|
||||
|
@ -2914,7 +2922,7 @@ class CGSpecializedSetter(CGAbstractExternMethod):
|
|||
"""
|
||||
def __init__(self, descriptor, attr):
|
||||
self.attr = attr
|
||||
name = 'set_' + attr.identifier.name
|
||||
name = 'set_' + descriptor.internalNameFor(attr.identifier.name)
|
||||
args = [Argument('*mut JSContext', 'cx'),
|
||||
Argument('HandleObject', 'obj'),
|
||||
Argument('*const %s' % descriptor.concreteType, 'this'),
|
||||
|
@ -2931,7 +2939,10 @@ class CGSpecializedSetter(CGAbstractExternMethod):
|
|||
@staticmethod
|
||||
def makeNativeName(descriptor, attr):
|
||||
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):
|
||||
|
@ -2948,9 +2959,9 @@ class CGStaticSetter(CGAbstractStaticBindingMethod):
|
|||
self.attr)
|
||||
checkForArg = CGGeneric(
|
||||
"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"
|
||||
" return 0;\n"
|
||||
" return JSFalse;\n"
|
||||
"}" % self.attr.identifier.name)
|
||||
call = CGSetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor,
|
||||
self.attr)
|
||||
|
@ -3045,8 +3056,9 @@ class CGMemberJITInfo(CGThing):
|
|||
|
||||
def define(self):
|
||||
if self.member.isAttr():
|
||||
getterinfo = ("%s_getterinfo" % self.member.identifier.name)
|
||||
getter = ("get_%s" % self.member.identifier.name)
|
||||
internalMemberName = self.descriptor.internalNameFor(self.member.identifier.name)
|
||||
getterinfo = ("%s_getterinfo" % internalMemberName)
|
||||
getter = ("get_%s" % internalMemberName)
|
||||
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
|
||||
|
||||
movable = self.mayBeMovable() and getterinfal
|
||||
|
@ -3070,8 +3082,8 @@ class CGMemberJITInfo(CGThing):
|
|||
slotIndex,
|
||||
[self.member.type], None)
|
||||
if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards")):
|
||||
setterinfo = ("%s_setterinfo" % self.member.identifier.name)
|
||||
setter = ("set_%s" % self.member.identifier.name)
|
||||
setterinfo = ("%s_setterinfo" % internalMemberName)
|
||||
setter = ("set_%s" % internalMemberName)
|
||||
# Setters are always fallible, since they have to do a typed unwrap.
|
||||
result += self.defineJitInfo(setterinfo, setter, "Setter",
|
||||
False, False, "AliasEverything",
|
||||
|
@ -3966,7 +3978,23 @@ class CGProxyIndexedSetter(CGProxySpecialOperation):
|
|||
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
|
||||
the returned value will be wrapped with wrapForType using templateValues.
|
||||
|
@ -3976,7 +4004,16 @@ class CGProxyNamedGetter(CGProxySpecialOperation):
|
|||
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.
|
||||
"""
|
||||
|
@ -3984,7 +4021,7 @@ class CGProxyNamedSetter(CGProxySpecialOperation):
|
|||
CGProxySpecialOperation.__init__(self, descriptor, 'NamedSetter')
|
||||
|
||||
|
||||
class CGProxyNamedDeleter(CGProxySpecialOperation):
|
||||
class CGProxyNamedDeleter(CGProxyNamedOperation):
|
||||
"""
|
||||
Class to generate a call to a named deleter.
|
||||
"""
|
||||
|
@ -3996,7 +4033,8 @@ class CGProxyUnwrap(CGAbstractMethod):
|
|||
def __init__(self, descriptor):
|
||||
args = [Argument('HandleObject', 'obj')]
|
||||
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy",
|
||||
'*const ' + descriptor.concreteType, args, alwaysInline=True)
|
||||
'*const ' + descriptor.concreteType, args,
|
||||
alwaysInline=True, unsafe=True)
|
||||
|
||||
def definition_body(self):
|
||||
return CGGeneric("""\
|
||||
|
@ -4057,9 +4095,6 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
|
|||
# properties that shadow prototype properties.
|
||||
namedGet = ("\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" +
|
||||
"}\n")
|
||||
else:
|
||||
|
@ -4121,9 +4156,6 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
|||
if not self.descriptor.operations['NamedCreator'] is namedSetter:
|
||||
raise TypeError("Can't handle creator that's different from the setter")
|
||||
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() +
|
||||
" (*opresult).code_ = 0; /* SpecialCodes::OkCode */\n" +
|
||||
" return JSTrue;\n" +
|
||||
|
@ -4132,9 +4164,6 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
|||
"}\n")
|
||||
else:
|
||||
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() +
|
||||
" if (found) {\n"
|
||||
# TODO(Issue 5876)
|
||||
|
@ -4165,10 +4194,7 @@ class CGDOMJSProxyHandler_delete(CGAbstractExternMethod):
|
|||
def getBody(self):
|
||||
set = ""
|
||||
if self.descriptor.operations['NamedDeleter']:
|
||||
set += ("let name = jsid_to_str(cx, id);\n" +
|
||||
"let this = UnwrapProxy(proxy);\n" +
|
||||
"let this = &*this;\n" +
|
||||
"%s") % (CGProxyNamedDeleter(self.descriptor).define())
|
||||
set += CGProxyNamedDeleter(self.descriptor).define()
|
||||
set += "return proxyhandler::delete(%s) as u8;" % ", ".join(a.name for a in self.args)
|
||||
return set
|
||||
|
||||
|
@ -4205,7 +4231,7 @@ class CGDOMJSProxyHandler_ownPropertyKeys(CGAbstractExternMethod):
|
|||
for name in (*unwrapped_proxy).SupportedPropertyNames() {
|
||||
let cstring = CString::new(name).unwrap();
|
||||
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 rooted_jsid = RootedId::new(cx, jsid);
|
||||
AppendToAutoIdVector(props, rooted_jsid.handle().get());
|
||||
|
@ -4253,9 +4279,6 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
|
|||
namedGetter = self.descriptor.operations['NamedGetter']
|
||||
if namedGetter:
|
||||
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" +
|
||||
" *bp = found as u8;\n"
|
||||
" return JSTrue;\n"
|
||||
|
@ -4328,10 +4351,7 @@ if !expando.ptr.is_null() {
|
|||
|
||||
namedGetter = self.descriptor.operations['NamedGetter']
|
||||
if namedGetter:
|
||||
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" +
|
||||
getNamed = ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
|
||||
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
|
||||
"}\n")
|
||||
else:
|
||||
|
@ -4564,7 +4584,7 @@ class CGInterfaceTrait(CGThing):
|
|||
return "".join(", %s: %s" % argument for argument in arguments)
|
||||
|
||||
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()
|
||||
]
|
||||
if methods:
|
||||
|
@ -5499,7 +5519,7 @@ class CallbackMember(CGNativeMember):
|
|||
conversion = (
|
||||
CGIfWrapper(CGGeneric(conversion),
|
||||
"%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"
|
||||
" argc -= 1;\n"
|
||||
"} else {\n"
|
||||
|
@ -5532,6 +5552,8 @@ class CallbackMember(CGNativeMember):
|
|||
"}\n")
|
||||
|
||||
def getArgcDecl(self):
|
||||
if self.argCount <= 1:
|
||||
return CGGeneric("let argc = %s;" % self.argCountStr)
|
||||
return CGGeneric("let mut argc = %s;" % self.argCountStr)
|
||||
|
||||
@staticmethod
|
||||
|
@ -5773,12 +5795,17 @@ class GlobalGenRoots():
|
|||
CGGeneric("use std::mem;\n\n")]
|
||||
for descriptor in descriptors:
|
||||
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:
|
||||
protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base',
|
||||
descriptor.concreteType))]
|
||||
derived = [CGGeneric('pub trait %s : Sized { fn %s(&self) -> bool; }\n' %
|
||||
(name + 'Derived', 'is_' + name.lower()))]
|
||||
derived = [CGGeneric("""\
|
||||
/// 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]:
|
||||
protoDescriptor = config.getDescriptor(protoName)
|
||||
delegate = string.Template("""\
|
||||
|
@ -5800,6 +5827,8 @@ impl ${selfName} for ${baseName} {
|
|||
pub struct ${name}Cast;
|
||||
impl ${name}Cast {
|
||||
#[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}> {
|
||||
match base.${checkFn}() {
|
||||
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]
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn to_layout_js<T: ${toBound}+Reflectable>(base: &LayoutJS<T>) -> Option<LayoutJS<${name}>> {
|
||||
|
@ -5835,15 +5856,11 @@ impl ${name}Cast {
|
|||
}
|
||||
|
||||
#[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} {
|
||||
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]
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn from_layout_js<T: ${fromBound}+Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<${name}> {
|
||||
|
|
|
@ -263,6 +263,8 @@ class Descriptor(DescriptorProvider):
|
|||
self._binaryNames.setdefault('__legacycaller', 'LegacyCall')
|
||||
self._binaryNames.setdefault('__stringifier', 'Stringifier')
|
||||
|
||||
self._internalNames = desc.get('internalNames', {})
|
||||
|
||||
for member in self.interface.members:
|
||||
if not member.isAttr() and not member.isMethod():
|
||||
continue
|
||||
|
@ -272,6 +274,8 @@ class Descriptor(DescriptorProvider):
|
|||
assert len(binaryName) == 1
|
||||
self._binaryNames.setdefault(member.identifier.name,
|
||||
binaryName[0])
|
||||
self._internalNames.setdefault(member.identifier.name,
|
||||
member.identifier.name.replace('-', '_'))
|
||||
|
||||
# Build the prototype chain.
|
||||
self.prototypeChain = []
|
||||
|
@ -285,6 +289,9 @@ class Descriptor(DescriptorProvider):
|
|||
def binaryNameFor(self, 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 maybeAppendInfallibleToAttrs(attrs, throws):
|
||||
if throws is None:
|
||||
|
|
|
@ -12,9 +12,8 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
|||
use dom::bindings::conversions::native_from_reflector_jsmanaged;
|
||||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::DocumentHelpers;
|
||||
use dom::window::{self, WindowHelpers, ScriptHelpers};
|
||||
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
|
||||
use dom::window::{self, ScriptHelpers};
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use script_task::{ScriptChan, ScriptPort, CommonScriptMsg, ScriptTask};
|
||||
|
||||
use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
|
||||
|
|
|
@ -207,6 +207,7 @@ impl MutHeapJSVal {
|
|||
/// `JS<T>`.
|
||||
#[must_root]
|
||||
#[derive(JSTraceable)]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct MutHeap<T: HeapGCValue + Copy> {
|
||||
val: Cell<T>,
|
||||
}
|
||||
|
@ -433,11 +434,6 @@ impl<T: Reflectable> Root<T> {
|
|||
&**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
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn from_rooted(js: JS<T>) -> Root<T> {
|
||||
|
|
|
@ -168,15 +168,13 @@ pub mod codegen {
|
|||
pub mod PrototypeList {
|
||||
include!(concat!(env!("OUT_DIR"), "/PrototypeList.rs"));
|
||||
}
|
||||
#[allow(unreachable_code, non_camel_case_types, non_upper_case_globals, unused_parens,
|
||||
unused_imports, unused_variables, unused_unsafe, unused_mut, unused_assignments,
|
||||
dead_code)]
|
||||
#[allow(non_camel_case_types, non_upper_case_globals,
|
||||
unused_imports, unused_variables, unused_assignments)]
|
||||
pub mod RegisterBindings {
|
||||
include!(concat!(env!("OUT_DIR"), "/RegisterBindings.rs"));
|
||||
}
|
||||
#[allow(unreachable_code, non_camel_case_types, non_upper_case_globals, unused_parens,
|
||||
unused_imports, unused_variables, unused_unsafe, unused_mut, unused_assignments,
|
||||
dead_code)]
|
||||
#[allow(non_camel_case_types, non_upper_case_globals,
|
||||
unused_imports, unused_variables, unused_assignments)]
|
||||
pub mod UnionTypes {
|
||||
include!(concat!(env!("OUT_DIR"), "/UnionTypes.rs"));
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use num::Float;
|
|||
use std::ops::Deref;
|
||||
|
||||
/// Encapsulates the IDL restricted float type.
|
||||
#[derive(JSTraceable,Clone,Eq,PartialEq)]
|
||||
#[derive(JSTraceable, Clone, Eq, PartialEq)]
|
||||
pub struct Finite<T: Float>(T);
|
||||
|
||||
unsafe impl<T: Float> Zeroable for Finite<T> {}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
//! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to
|
||||
//! a datatype.
|
||||
|
||||
use dom::bindings::js::JS;
|
||||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler};
|
||||
use script_task::ScriptChan;
|
||||
|
@ -69,6 +69,7 @@ use std::collections::{HashMap, HashSet};
|
|||
use std::ffi::CString;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::intrinsics::return_address;
|
||||
use std::iter::{FromIterator, IntoIterator};
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
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
|
||||
pub unsafe fn trace_traceables(tracer: *mut JSTracer) {
|
||||
ROOTED_TRACEABLES.with(|ref traceables| {
|
||||
|
|
|
@ -25,7 +25,6 @@ pub enum BlobTypeId {
|
|||
|
||||
// http://dev.w3.org/2006/webapi/FileAPI/#blob
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Blob {
|
||||
reflector_: Reflector,
|
||||
type_: BlobTypeId,
|
||||
|
@ -78,21 +77,15 @@ impl Blob {
|
|||
};
|
||||
Ok(Blob::new(global, bytes, &typeString.to_ascii_lowercase()))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BlobHelpers {
|
||||
fn read_out_buffer(self, send: Sender<Vec<u8>>);
|
||||
}
|
||||
|
||||
impl<'a> BlobHelpers for &'a Blob {
|
||||
fn read_out_buffer(self, send: Sender<Vec<u8>>) {
|
||||
pub fn read_out_buffer(&self, send: Sender<Vec<u8>>) {
|
||||
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
|
||||
fn Size(self) -> u64 {
|
||||
fn Size(&self) -> u64 {
|
||||
match self.bytes {
|
||||
None => 0,
|
||||
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
|
||||
fn Type(self) -> DOMString {
|
||||
fn Type(&self) -> DOMString {
|
||||
self.typeString.clone()
|
||||
}
|
||||
|
||||
// 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> {
|
||||
let size: i64 = self.Size().to_i64().unwrap();
|
||||
let relativeStart: i64 = match start {
|
||||
|
@ -153,12 +146,12 @@ impl<'a> BlobMethods for &'a Blob {
|
|||
}
|
||||
|
||||
// https://dev.w3.org/2006/webapi/FileAPI/#dfn-isClosed
|
||||
fn IsClosed(self) -> bool {
|
||||
fn IsClosed(&self) -> bool {
|
||||
self.isClosed_.get()
|
||||
}
|
||||
|
||||
// https://dev.w3.org/2006/webapi/FileAPI/#dfn-close
|
||||
fn Close(self) {
|
||||
fn Close(&self) {
|
||||
// Step 1
|
||||
if self.isClosed_.get() {
|
||||
return;
|
||||
|
|
|
@ -8,10 +8,9 @@ use dom::bindings::js::{JS, Root};
|
|||
use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor};
|
||||
use dom::bindings::utils::get_array_index_from_id;
|
||||
use dom::bindings::utils::{Reflectable, WindowProxyHandler};
|
||||
use dom::document::{Document, DocumentHelpers};
|
||||
use dom::document::Document;
|
||||
use dom::element::Element;
|
||||
use dom::window::Window;
|
||||
use dom::window::WindowHelpers;
|
||||
|
||||
use js::glue::{GetProxyPrivate};
|
||||
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
|
||||
|
|
|
@ -16,7 +16,6 @@ use dom::canvasrenderingcontext2d::parse_color;
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#canvasgradient
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CanvasGradient {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn AddColorStop(self, offset: Finite<f64>, color: String) -> ErrorResult {
|
||||
fn AddColorStop(&self, offset: Finite<f64>, color: String) -> ErrorResult {
|
||||
if *offset < 0f64 || *offset > 1f64 {
|
||||
return Err(IndexSize);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ use euclid::size::Size2D;
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#canvaspattern
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CanvasPattern {
|
||||
reflector_: Reflector,
|
||||
surface_data: Vec<u8>,
|
||||
|
|
|
@ -17,11 +17,11 @@ use dom::bindings::num::Finite;
|
|||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle};
|
||||
use dom::canvaspattern::CanvasPattern;
|
||||
use dom::htmlcanvaselement::HTMLCanvasElement;
|
||||
use dom::htmlcanvaselement::utils as canvas_utils;
|
||||
use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers};
|
||||
use dom::htmlimageelement::{HTMLImageElement, HTMLImageElementHelpers};
|
||||
use dom::imagedata::{ImageData, ImageDataHelpers};
|
||||
use dom::node::{window_from_node, NodeHelpers, NodeDamage};
|
||||
use dom::htmlimageelement::HTMLImageElement;
|
||||
use dom::imagedata::ImageData;
|
||||
use dom::node::{window_from_node, NodeDamage};
|
||||
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use net_traits::image::base::PixelFormat;
|
||||
|
@ -61,7 +61,6 @@ pub enum CanvasFillOrStrokeStyle {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CanvasRenderingContext2D {
|
||||
reflector_: Reflector,
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CanvasRenderingContext2DHelpers {
|
||||
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 {
|
||||
pub fn get_renderer_id(&self) -> usize {
|
||||
self.renderer_id
|
||||
}
|
||||
fn get_ipc_renderer(self) -> IpcSender<CanvasMsg> {
|
||||
pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
|
||||
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.
|
||||
//
|
||||
// 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
|
||||
fn Canvas(self) -> Root<HTMLCanvasElement> {
|
||||
fn Canvas(&self) -> Root<HTMLCanvasElement> {
|
||||
self.canvas.root()
|
||||
}
|
||||
|
||||
// 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.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap();
|
||||
}
|
||||
|
||||
// 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();
|
||||
if let Some(state) = saved_states.pop() {
|
||||
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
|
||||
fn Scale(self, x: f64, y: f64) {
|
||||
fn Scale(&self, x: f64, y: f64) {
|
||||
if !(x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
}
|
||||
|
@ -484,7 +476,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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() {
|
||||
return;
|
||||
}
|
||||
|
@ -498,7 +490,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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()) {
|
||||
return;
|
||||
}
|
||||
|
@ -509,7 +501,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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() &&
|
||||
d.is_finite() && e.is_finite() && f.is_finite()) {
|
||||
return;
|
||||
|
@ -526,7 +518,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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() &&
|
||||
d.is_finite() && e.is_finite() && f.is_finite()) {
|
||||
return;
|
||||
|
@ -542,19 +534,19 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform
|
||||
fn ResetTransform(self) {
|
||||
fn ResetTransform(&self) {
|
||||
self.state.borrow_mut().transform = Matrix2D::identity();
|
||||
self.update_transform()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
|
||||
fn GlobalAlpha(self) -> f64 {
|
||||
fn GlobalAlpha(&self) -> f64 {
|
||||
let state = self.state.borrow();
|
||||
state.global_alpha
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -566,7 +558,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
|
||||
fn GlobalCompositeOperation(self) -> DOMString {
|
||||
fn GlobalCompositeOperation(&self) -> DOMString {
|
||||
let state = self.state.borrow();
|
||||
match state.global_composition {
|
||||
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
|
||||
fn SetGlobalCompositeOperation(self, op_str: DOMString) {
|
||||
fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
|
||||
if let Some(op) = CompositionOrBlending::from_str(&op_str) {
|
||||
self.state.borrow_mut().global_composition = op;
|
||||
self.ipc_renderer
|
||||
|
@ -585,7 +577,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap();
|
||||
self.mark_as_dirty();
|
||||
|
@ -593,7 +585,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
self.ipc_renderer
|
||||
.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
|
||||
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) {
|
||||
self.ipc_renderer
|
||||
.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
|
||||
fn BeginPath(self) {
|
||||
fn BeginPath(&self) {
|
||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap();
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
|
||||
fn Fill(self, _: CanvasWindingRule) {
|
||||
fn Fill(&self, _: CanvasWindingRule) {
|
||||
// TODO: Process winding rule
|
||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap();
|
||||
self.mark_as_dirty();
|
||||
}
|
||||
|
||||
// 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.mark_as_dirty();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
|
||||
fn Clip(self, _: CanvasWindingRule) {
|
||||
fn Clip(&self, _: CanvasWindingRule) {
|
||||
// TODO: Process winding rule
|
||||
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Clip)).unwrap();
|
||||
}
|
||||
|
||||
// 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<()> {
|
||||
if !(dx.is_finite() && dy.is_finite()) {
|
||||
return Ok(());
|
||||
|
@ -652,7 +644,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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<()> {
|
||||
if !(dx.is_finite() && dy.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
|
||||
fn DrawImage__(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
fn DrawImage__(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
sx: f64, sy: f64, sw: f64, sh: f64,
|
||||
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
|
||||
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
|
||||
fn MoveTo(self, x: f64, y: f64) {
|
||||
fn MoveTo(&self, x: f64, y: f64) {
|
||||
if !(x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
}
|
||||
|
@ -687,7 +679,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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()) {
|
||||
return;
|
||||
}
|
||||
|
@ -699,7 +691,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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()) {
|
||||
let rect = Rect::new(Point2D::new(x as f32, y 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
|
||||
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() &&
|
||||
x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
|
@ -723,7 +715,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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() &&
|
||||
x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
|
@ -738,7 +730,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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<()> {
|
||||
if !([x, y, r, start, end].iter().all(|x| x.is_finite())) {
|
||||
return Ok(());
|
||||
|
@ -758,7 +750,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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())) {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -776,18 +768,18 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled
|
||||
fn ImageSmoothingEnabled(self) -> bool {
|
||||
fn ImageSmoothingEnabled(&self) -> bool {
|
||||
let state = self.state.borrow();
|
||||
state.image_smoothing_enabled
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
|
||||
fn StrokeStyle(self) -> StringOrCanvasGradientOrCanvasPattern {
|
||||
fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
|
||||
match self.state.borrow().stroke_style {
|
||||
CanvasFillOrStrokeStyle::Color(ref rgba) => {
|
||||
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
|
||||
fn SetStrokeStyle(self, value: StringOrCanvasGradientOrCanvasPattern) {
|
||||
fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
|
||||
match value {
|
||||
StringOrCanvasGradientOrCanvasPattern::eString(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
|
||||
fn FillStyle(self) -> StringOrCanvasGradientOrCanvasPattern {
|
||||
fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
|
||||
match self.state.borrow().fill_style {
|
||||
CanvasFillOrStrokeStyle::Color(ref rgba) => {
|
||||
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
|
||||
fn SetFillStyle(self, value: StringOrCanvasGradientOrCanvasPattern) {
|
||||
fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
|
||||
match value {
|
||||
StringOrCanvasGradientOrCanvasPattern::eString(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
|
||||
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 {
|
||||
return Err(IndexSize)
|
||||
}
|
||||
|
@ -878,12 +870,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
|
||||
fn GetImageData(self,
|
||||
fn GetImageData(&self,
|
||||
sx: Finite<f64>,
|
||||
sy: 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
|
||||
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),
|
||||
Finite::wrap(imagedata.Width() as f64), Finite::wrap(imagedata.Height() as f64))
|
||||
}
|
||||
|
||||
// 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>) {
|
||||
let data = imagedata.get_data_array(&self.global.root().r());
|
||||
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
|
||||
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> {
|
||||
CanvasGradient::new(self.global.root().r(),
|
||||
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())))
|
||||
}
|
||||
|
||||
// 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>)
|
||||
-> Fallible<Root<CanvasGradient>> {
|
||||
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
|
||||
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
fn CreatePattern(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
|
||||
repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
|
||||
let (image_data, image_size) = match image {
|
||||
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
|
||||
|
@ -1024,13 +1016,13 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
|
||||
fn LineWidth(self) -> f64 {
|
||||
fn LineWidth(&self) -> f64 {
|
||||
let state = self.state.borrow();
|
||||
state.line_width
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -1042,7 +1034,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
|
||||
fn LineCap(self) -> DOMString {
|
||||
fn LineCap(&self) -> DOMString {
|
||||
let state = self.state.borrow();
|
||||
match state.line_cap {
|
||||
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
|
||||
fn SetLineCap(self, cap_str: DOMString) {
|
||||
fn SetLineCap(&self, cap_str: DOMString) {
|
||||
if let Some(cap) = LineCapStyle::from_str(&cap_str) {
|
||||
self.state.borrow_mut().line_cap = cap;
|
||||
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
|
||||
fn LineJoin(self) -> DOMString {
|
||||
fn LineJoin(&self) -> DOMString {
|
||||
let state = self.state.borrow();
|
||||
match state.line_join {
|
||||
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
|
||||
fn SetLineJoin(self, join_str: DOMString) {
|
||||
fn SetLineJoin(&self, join_str: DOMString) {
|
||||
if let Some(join) = LineJoinStyle::from_str(&join_str) {
|
||||
self.state.borrow_mut().line_join = join;
|
||||
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
|
||||
fn MiterLimit(self) -> f64 {
|
||||
fn MiterLimit(&self) -> f64 {
|
||||
let state = self.state.borrow();
|
||||
state.miter_limit
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -1096,12 +1088,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
|
||||
fn ShadowOffsetX(self) -> f64 {
|
||||
fn ShadowOffsetX(&self) -> f64 {
|
||||
self.state.borrow().shadow_offset_x
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -1110,12 +1102,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
|
||||
fn ShadowOffsetY(self) -> f64 {
|
||||
fn ShadowOffsetY(&self) -> f64 {
|
||||
self.state.borrow().shadow_offset_y
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -1124,12 +1116,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
|
||||
fn ShadowBlur(self) -> f64 {
|
||||
fn ShadowBlur(&self) -> f64 {
|
||||
self.state.borrow().shadow_blur
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -1138,14 +1130,14 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
|
||||
fn ShadowColor(self) -> DOMString {
|
||||
fn ShadowColor(&self) -> DOMString {
|
||||
let mut result = String::new();
|
||||
serialize(&self.state.borrow().shadow_color, &mut result).unwrap();
|
||||
result
|
||||
}
|
||||
|
||||
// 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) {
|
||||
self.state.borrow_mut().shadow_color = color;
|
||||
self.ipc_renderer
|
||||
|
|
|
@ -15,16 +15,15 @@ use dom::bindings::js::{LayoutJS, Root};
|
|||
use dom::document::Document;
|
||||
use dom::element::Element;
|
||||
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::cell::Ref;
|
||||
|
||||
// https://dom.spec.whatwg.org/#characterdata
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CharacterData {
|
||||
node: Node,
|
||||
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
|
||||
fn Data(self) -> DOMString {
|
||||
fn Data(&self) -> DOMString {
|
||||
self.data.borrow().clone()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-data
|
||||
fn SetData(self, data: DOMString) {
|
||||
fn SetData(&self, data: DOMString) {
|
||||
*self.data.borrow_mut() = data;
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-length
|
||||
fn Length(self) -> u32 {
|
||||
self.data.borrow().chars().count() as u32
|
||||
fn Length(&self) -> u32 {
|
||||
self.data.borrow().chars().map(|c| c.len_utf16()).sum::<usize>() as u32
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-substringdataoffset-count
|
||||
fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> {
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-substringdata
|
||||
fn SubstringData(&self, offset: u32, count: u32) -> Fallible<DOMString> {
|
||||
let data = self.data.borrow();
|
||||
// Step 1.
|
||||
let length = data.chars().count() as u32;
|
||||
if offset > length {
|
||||
let data_from_offset = match find_utf16_code_unit_offset(&data, offset) {
|
||||
Some(offset_bytes) => &data[offset_bytes..],
|
||||
// Step 2.
|
||||
return Err(IndexSize);
|
||||
}
|
||||
// Steps 3-4.
|
||||
let end = if length - offset < count { length } else { offset + count };
|
||||
Ok(slice_chars(&*data, offset as usize, end as usize).to_owned())
|
||||
None => return Err(IndexSize)
|
||||
};
|
||||
let substring = match find_utf16_code_unit_offset(data_from_offset, count) {
|
||||
// Steps 3.
|
||||
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
|
||||
fn AppendData(self, data: DOMString) {
|
||||
fn AppendData(&self, data: DOMString) {
|
||||
self.append_data(&*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)
|
||||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-replacedataoffset-count-data
|
||||
fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
|
||||
// Step 1.
|
||||
let length = self.data.borrow().chars().count() as u32;
|
||||
if offset > length {
|
||||
// Step 2.
|
||||
return Err(IndexSize);
|
||||
}
|
||||
// Step 3.
|
||||
let count = match length - offset {
|
||||
diff if diff < count => diff,
|
||||
_ => count,
|
||||
// https://dom.spec.whatwg.org/#dom-characterdata-replacedata
|
||||
fn ReplaceData(&self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
|
||||
let new_data = {
|
||||
let data = self.data.borrow();
|
||||
let (prefix, data_from_offset) = match find_utf16_code_unit_offset(&data, offset) {
|
||||
Some(offset_bytes) => data.split_at(offset_bytes),
|
||||
// Step 2.
|
||||
None => return Err(IndexSize)
|
||||
};
|
||||
let suffix = match find_utf16_code_unit_offset(data_from_offset, count) {
|
||||
// Steps 3.
|
||||
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.
|
||||
// Step 5.
|
||||
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
|
||||
*self.data.borrow_mut() = new_data;
|
||||
// FIXME: Once we have `Range`, we should implement step 8 to step 11
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-childnode-remove
|
||||
fn Remove(self) {
|
||||
fn Remove(&self) {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.remove_self();
|
||||
}
|
||||
|
||||
// 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()
|
||||
.filter_map(ElementCast::to_root).next()
|
||||
}
|
||||
|
||||
// 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()
|
||||
.filter_map(ElementCast::to_root).next()
|
||||
}
|
||||
|
@ -158,18 +165,14 @@ pub enum CharacterDataTypeId {
|
|||
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]
|
||||
fn data(self) -> Ref<'a, DOMString> {
|
||||
pub fn data(&self) -> Ref<DOMString> {
|
||||
self.data.borrow()
|
||||
}
|
||||
#[inline]
|
||||
fn append_data(self, data: &str) {
|
||||
pub fn append_data(&self, data: &str) {
|
||||
self.data.borrow_mut().push_str(data)
|
||||
}
|
||||
}
|
||||
|
@ -186,3 +189,32 @@ impl LayoutCharacterDataHelpers for LayoutJS<CharacterData> {
|
|||
&(*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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ use script_task::ScriptChan;
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CloseEvent {
|
||||
event: Event,
|
||||
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
|
||||
fn WasClean(self) -> bool {
|
||||
fn WasClean(&self) -> bool {
|
||||
self.wasClean
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-closeevent-code
|
||||
fn Code(self) -> u16 {
|
||||
fn Code(&self) -> u16 {
|
||||
self.code
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-closeevent-reason
|
||||
fn Reason(self) -> DOMString {
|
||||
fn Reason(&self) -> DOMString {
|
||||
self.reason.clone()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ use util::str::DOMString;
|
|||
|
||||
/// An HTML comment.
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Comment {
|
||||
characterdata: CharacterData,
|
||||
}
|
||||
|
@ -44,4 +43,3 @@ impl Comment {
|
|||
Ok(Comment::new(data, document.r()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,10 @@ use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
|
|||
use dom::bindings::global::{GlobalRef, GlobalField};
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::window::WindowHelpers;
|
||||
use util::str::DOMString;
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Console
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Console {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn Log(self, messages: Vec<DOMString>) {
|
||||
fn Log(&self, messages: Vec<DOMString>) {
|
||||
for message in messages {
|
||||
println!("{}", 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
|
||||
fn Debug(self, messages: Vec<DOMString>) {
|
||||
fn Debug(&self, messages: Vec<DOMString>) {
|
||||
for message in messages {
|
||||
println!("{}", 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
|
||||
fn Info(self, messages: Vec<DOMString>) {
|
||||
fn Info(&self, messages: Vec<DOMString>) {
|
||||
for message in messages {
|
||||
println!("{}", 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
|
||||
fn Warn(self, messages: Vec<DOMString>) {
|
||||
fn Warn(&self, messages: Vec<DOMString>) {
|
||||
for message in messages {
|
||||
println!("{}", 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
|
||||
fn Error(self, messages: Vec<DOMString>) {
|
||||
fn Error(&self, messages: Vec<DOMString>) {
|
||||
for message in messages {
|
||||
println!("{}", 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
|
||||
fn Assert(self, condition: bool, message: Option<DOMString>) {
|
||||
fn Assert(&self, condition: bool, message: Option<DOMString>) {
|
||||
if !condition {
|
||||
let message = match message {
|
||||
Some(ref message) => &**message,
|
||||
|
|
|
@ -22,7 +22,6 @@ no_jsmanaged_fields!(OsRng);
|
|||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Crypto {
|
||||
reflector_: Reflector,
|
||||
rng: DOMRefCell<OsRng>,
|
||||
|
@ -41,10 +40,10 @@ impl Crypto {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> CryptoMethods for &'a Crypto {
|
||||
impl CryptoMethods for Crypto {
|
||||
#[allow(unsafe_code)]
|
||||
// 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> {
|
||||
let mut length = 0;
|
||||
let mut data = ptr::null_mut();
|
||||
|
|
|
@ -10,7 +10,6 @@ use util::str::DOMString;
|
|||
use cssparser::serialize_identifier;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CSS {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
|
|
@ -8,10 +8,9 @@ use dom::bindings::error::{Error, ErrorResult, Fallible};
|
|||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::document::DocumentHelpers;
|
||||
use dom::element::{ElementHelpers, StylePriority, Element};
|
||||
use dom::node::{window_from_node, document_from_node, NodeDamage, NodeHelpers};
|
||||
use dom::window::{Window, WindowHelpers};
|
||||
use dom::element::{StylePriority, Element};
|
||||
use dom::node::{window_from_node, document_from_node, NodeDamage};
|
||||
use dom::window::Window;
|
||||
use selectors::parser::PseudoElement;
|
||||
use string_cache::Atom;
|
||||
use style::properties::PropertyDeclaration;
|
||||
|
@ -24,7 +23,6 @@ use std::cell::Ref;
|
|||
|
||||
// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CSSStyleDeclaration {
|
||||
reflector_: Reflector,
|
||||
owner: JS<Element>,
|
||||
|
@ -41,10 +39,10 @@ pub enum CSSModificationAccess {
|
|||
macro_rules! css_properties(
|
||||
( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => (
|
||||
$(
|
||||
fn $getter(self) -> DOMString {
|
||||
fn $getter(&self) -> DOMString {
|
||||
self.GetPropertyValue($cssprop.to_owned())
|
||||
}
|
||||
fn $setter(self, value: DOMString) -> ErrorResult {
|
||||
fn $setter(&self, value: DOMString) -> ErrorResult {
|
||||
self.SetPropertyValue($cssprop.to_owned(), value)
|
||||
}
|
||||
)*
|
||||
|
@ -76,9 +74,7 @@ impl CSSStyleDeclaration {
|
|||
GlobalRef::Window(global),
|
||||
CSSStyleDeclarationBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl CSSStyleDeclaration {
|
||||
fn get_computed_style(&self, property: &Atom) -> Option<DOMString> {
|
||||
let owner = self.owner.root();
|
||||
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
|
||||
fn Length(self) -> u32 {
|
||||
fn Length(&self) -> u32 {
|
||||
let owner = self.owner.root();
|
||||
let elem = ElementCast::from_ref(owner.r());
|
||||
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
|
||||
fn Item(self, index: u32) -> DOMString {
|
||||
fn Item(&self, index: u32) -> DOMString {
|
||||
let index = index as usize;
|
||||
let owner = self.owner.root();
|
||||
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
|
||||
fn GetPropertyValue(self, property: DOMString) -> DOMString {
|
||||
fn GetPropertyValue(&self, property: DOMString) -> DOMString {
|
||||
let owner = self.owner.root();
|
||||
|
||||
// Step 1
|
||||
|
@ -169,7 +165,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
|||
}
|
||||
|
||||
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
|
||||
fn GetPropertyPriority(self, property: DOMString) -> DOMString {
|
||||
fn GetPropertyPriority(&self, property: DOMString) -> DOMString {
|
||||
// Step 1
|
||||
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
|
||||
fn SetProperty(self, property: DOMString, value: DOMString,
|
||||
fn SetProperty(&self, property: DOMString, value: DOMString,
|
||||
priority: DOMString) -> ErrorResult {
|
||||
// Step 1
|
||||
if self.readonly {
|
||||
|
@ -252,7 +248,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
|||
}
|
||||
|
||||
// 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
|
||||
if self.readonly {
|
||||
return Err(Error::NoModificationAllowed);
|
||||
|
@ -286,12 +282,12 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
|||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
|
||||
// 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
|
||||
if self.readonly {
|
||||
return Err(Error::NoModificationAllowed);
|
||||
|
@ -322,21 +318,22 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
|
|||
}
|
||||
|
||||
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
|
||||
fn CssFloat(self) -> DOMString {
|
||||
fn CssFloat(&self) -> DOMString {
|
||||
self.GetPropertyValue("float".to_owned())
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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);
|
||||
*found = index < self.Length();
|
||||
rval
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom/#cssstyledeclaration
|
||||
css_properties_accessors!(css_properties);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ use util::str::DOMString;
|
|||
|
||||
// https://dom.spec.whatwg.org/#interface-customevent
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct CustomEvent {
|
||||
event: Event,
|
||||
#[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
|
||||
fn Detail(self, _cx: *mut JSContext) -> JSVal {
|
||||
fn Detail(&self, _cx: *mut JSContext) -> JSVal {
|
||||
self.detail.get()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent
|
||||
fn InitCustomEvent(self,
|
||||
fn InitCustomEvent(&self,
|
||||
_cx: *mut JSContext,
|
||||
type_: DOMString,
|
||||
can_bubble: bool,
|
||||
|
@ -85,4 +84,3 @@ impl<'a> CustomEventMethods for &'a CustomEvent {
|
|||
event.InitEvent(type_, can_bubble, cancelable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ use devtools;
|
|||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
|
||||
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::InheritTypes::DedicatedWorkerGlobalScopeDerived;
|
||||
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::structuredclone::StructuredCloneData;
|
||||
use dom::bindings::utils::Reflectable;
|
||||
use dom::errorevent::ErrorEvent;
|
||||
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::messageevent::MessageEvent;
|
||||
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler, WorkerErrorHandler};
|
||||
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
|
||||
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, SimpleWorkerErrorHandler};
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit};
|
||||
use script_task::ScriptTaskEventCategory::WorkerEvent;
|
||||
use script_task::{ScriptTask, ScriptChan, TimerSource, ScriptPort, StackRootTLS, CommonScriptMsg};
|
||||
|
||||
use devtools_traits::DevtoolScriptControlMsg;
|
||||
|
@ -138,7 +137,6 @@ enum MixedMessage {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DedicatedWorkerGlobalScope {
|
||||
workerglobalscope: WorkerGlobalScope,
|
||||
id: PipelineId,
|
||||
|
@ -189,9 +187,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
own_sender, receiver);
|
||||
DedicatedWorkerGlobalScopeBinding::Wrap(runtime.cx(), scope)
|
||||
}
|
||||
}
|
||||
|
||||
impl DedicatedWorkerGlobalScope {
|
||||
pub fn run_worker_scope(init: WorkerGlobalScopeInit,
|
||||
worker_url: Url,
|
||||
id: PipelineId,
|
||||
|
@ -210,8 +206,8 @@ impl DedicatedWorkerGlobalScope {
|
|||
let (url, source) = match load_whole_resource(&init.resource_task, worker_url) {
|
||||
Err(_) => {
|
||||
println!("error loading script {}", serialized_worker_url);
|
||||
parent_sender.send(CommonScriptMsg::RunnableMsg(
|
||||
box WorkerEventHandler::new(worker))).unwrap();
|
||||
parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
|
||||
box SimpleWorkerErrorHandler::new(worker))).unwrap();
|
||||
return;
|
||||
}
|
||||
Ok((metadata, bytes)) => {
|
||||
|
@ -244,28 +240,19 @@ impl DedicatedWorkerGlobalScope {
|
|||
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DedicatedWorkerGlobalScopeHelpers {
|
||||
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> {
|
||||
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
|
||||
box WorkerThreadWorkerChan {
|
||||
sender: self.own_sender.clone(),
|
||||
worker: self.worker.borrow().as_ref().unwrap().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn pipeline(self) -> PipelineId {
|
||||
pub fn pipeline(&self) -> PipelineId {
|
||||
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 chan = box SendableWorkerScriptChan {
|
||||
sender: tx,
|
||||
|
@ -274,21 +261,12 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
|
|||
(chan, box rx)
|
||||
}
|
||||
|
||||
fn process_event(self, msg: CommonScriptMsg) {
|
||||
pub fn process_event(&self, msg: CommonScriptMsg) {
|
||||
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)]
|
||||
fn receive_event(self) -> Result<MixedMessage, RecvError> {
|
||||
fn receive_event(&self) -> Result<MixedMessage, RecvError> {
|
||||
let scope = WorkerGlobalScopeCast::from_ref(self);
|
||||
let worker_port = &self.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 {
|
||||
WorkerScriptMsg::DOMMessage(data) => {
|
||||
let scope = WorkerGlobalScopeCast::from_ref(self);
|
||||
|
@ -323,7 +301,7 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
|
|||
data.read(GlobalRef::Worker(scope), message.handle_mut());
|
||||
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
|
||||
},
|
||||
WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(runnable)) => {
|
||||
WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
|
||||
runnable.handler()
|
||||
},
|
||||
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 {
|
||||
MixedMessage::FromDevtools(msg) => {
|
||||
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
|
||||
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 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();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage
|
||||
event_handler!(message, GetOnmessage, SetOnmessage);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,13 +15,12 @@ use dom::document::Document;
|
|||
use dom::element::Element;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
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 util::str::DOMString;
|
||||
|
||||
// https://dom.spec.whatwg.org/#documentfragment
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DocumentFragment {
|
||||
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
|
||||
fn Children(self) -> Root<HTMLCollection> {
|
||||
fn Children(&self) -> Root<HTMLCollection> {
|
||||
let window = window_from_node(self);
|
||||
HTMLCollection::children(window.r(), NodeCast::from_ref(self))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
|
||||
fn GetFirstElementChild(self) -> Option<Root<Element>> {
|
||||
fn GetFirstElementChild(&self) -> Option<Root<Element>> {
|
||||
NodeCast::from_ref(self).child_elements().next()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
|
||||
fn GetLastElementChild(self) -> Option<Root<Element>> {
|
||||
fn GetLastElementChild(&self) -> Option<Root<Element>> {
|
||||
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
|
||||
fn ChildElementCount(self) -> u32 {
|
||||
fn ChildElementCount(&self) -> u32 {
|
||||
NodeCast::from_ref(self).child_elements().count() as u32
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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);
|
||||
root.query_selector(selectors)
|
||||
}
|
||||
|
||||
// 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);
|
||||
root.query_selector_all(selectors)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use dom::bindings::error::ErrorResult;
|
|||
use dom::bindings::js::Root;
|
||||
use dom::document::Document;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::node::{Node, NodeHelpers, NodeTypeId};
|
||||
use dom::node::{Node, NodeTypeId};
|
||||
use util::str::DOMString;
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -18,7 +18,6 @@ use std::borrow::ToOwned;
|
|||
// https://dom.spec.whatwg.org/#documenttype
|
||||
/// The `DOCTYPE` tag.
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DocumentType {
|
||||
node: Node,
|
||||
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
|
||||
fn Name(self) -> DOMString {
|
||||
fn Name(&self) -> DOMString {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-documenttype-publicid
|
||||
fn PublicId(self) -> DOMString {
|
||||
fn PublicId(&self) -> DOMString {
|
||||
self.public_id.clone()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-documenttype-systemid
|
||||
fn SystemId(self) -> DOMString {
|
||||
fn SystemId(&self) -> DOMString {
|
||||
self.system_id.clone()
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-childnode-remove
|
||||
fn Remove(self) {
|
||||
fn Remove(&self) {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.remove_self();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ pub enum DOMErrorName {
|
|||
}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMException {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn Code(self) -> u16 {
|
||||
fn Code(&self) -> u16 {
|
||||
match self.code {
|
||||
// https://heycam.github.io/webidl/#dfn-throw
|
||||
DOMErrorName::EncodingError => 0,
|
||||
|
@ -71,12 +70,12 @@ impl<'a> DOMExceptionMethods for &'a DOMException {
|
|||
}
|
||||
|
||||
// https://heycam.github.io/webidl/#idl-DOMException-error-names
|
||||
fn Name(self) -> DOMString {
|
||||
fn Name(&self) -> DOMString {
|
||||
format!("{:?}", self.code)
|
||||
}
|
||||
|
||||
// https://heycam.github.io/webidl/#error-names
|
||||
fn Message(self) -> DOMString {
|
||||
fn Message(&self) -> DOMString {
|
||||
let message = match self.code {
|
||||
DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
|
||||
DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",
|
||||
|
|
|
@ -14,7 +14,7 @@ use dom::bindings::js::{JS, Root};
|
|||
use dom::bindings::utils::validate_qualified_name;
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::document::DocumentSource;
|
||||
use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
|
||||
use dom::document::{Document, IsHTMLDocument};
|
||||
use dom::documenttype::DocumentType;
|
||||
use dom::htmlbodyelement::HTMLBodyElement;
|
||||
use dom::htmlheadelement::HTMLHeadElement;
|
||||
|
@ -27,7 +27,6 @@ use std::borrow::ToOwned;
|
|||
|
||||
// https://dom.spec.whatwg.org/#domimplementation
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMImplementation {
|
||||
reflector_: Reflector,
|
||||
document: JS<Document>,
|
||||
|
@ -50,9 +49,9 @@ impl 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
|
||||
fn CreateDocumentType(self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
|
||||
fn CreateDocumentType(&self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
|
||||
-> Fallible<Root<DocumentType>> {
|
||||
try!(validate_qualified_name(&qualified_name));
|
||||
let document = self.document.root();
|
||||
|
@ -60,7 +59,7 @@ impl<'a> DOMImplementationMethods for &'a DOMImplementation {
|
|||
}
|
||||
|
||||
// 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>> {
|
||||
let doc = self.document.root();
|
||||
let doc = doc.r();
|
||||
|
@ -109,7 +108,7 @@ impl<'a> DOMImplementationMethods for &'a DOMImplementation {
|
|||
}
|
||||
|
||||
// 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 = document.r();
|
||||
let win = document.window();
|
||||
|
@ -168,7 +167,7 @@ impl<'a> DOMImplementationMethods for &'a DOMImplementation {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
|
||||
fn HasFeature(self) -> bool {
|
||||
fn HasFeature(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,14 @@ use dom::bindings::global::GlobalRef;
|
|||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::document::DocumentSource;
|
||||
use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
|
||||
use dom::window::{Window, WindowHelpers};
|
||||
use dom::document::{Document, IsHTMLDocument};
|
||||
use dom::window::Window;
|
||||
use parse::html::{ParseContext, parse_html};
|
||||
use util::str::DOMString;
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMParser {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn ParseFromString(self,
|
||||
fn ParseFromString(&self,
|
||||
s: DOMString,
|
||||
ty: DOMParserBinding::SupportedType)
|
||||
-> Fallible<Root<Document>> {
|
||||
|
@ -81,4 +80,3 @@ impl<'a> DOMParserMethods for &'a DOMParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ use dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
|
|||
|
||||
// http://dev.w3.org/fxtf/geometry/Overview.html#dompoint
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMPoint {
|
||||
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
|
||||
fn X(self) -> f64 {
|
||||
fn X(&self) -> f64 {
|
||||
self.point.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);
|
||||
}
|
||||
|
||||
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y
|
||||
fn Y(self) -> f64 {
|
||||
fn Y(&self) -> f64 {
|
||||
self.point.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);
|
||||
}
|
||||
|
||||
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z
|
||||
fn Z(self) -> f64 {
|
||||
fn Z(&self) -> f64 {
|
||||
self.point.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);
|
||||
}
|
||||
|
||||
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w
|
||||
fn W(self) -> f64 {
|
||||
fn W(&self) -> f64 {
|
||||
self.point.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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use std::cell::Cell;
|
|||
|
||||
// http://dev.w3.org/fxtf/geometry/Overview.html#dompointreadonly
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMPointReadOnly {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn X(self) -> f64 {
|
||||
fn X(&self) -> f64 {
|
||||
self.x.get()
|
||||
}
|
||||
|
||||
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y
|
||||
fn Y(self) -> f64 {
|
||||
fn Y(&self) -> f64 {
|
||||
self.y.get()
|
||||
}
|
||||
|
||||
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z
|
||||
fn Z(self) -> f64 {
|
||||
fn Z(&self) -> f64 {
|
||||
self.z.get()
|
||||
}
|
||||
|
||||
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w
|
||||
fn W(self) -> f64 {
|
||||
fn W(&self) -> f64 {
|
||||
self.w.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DOMPointWriteMethods {
|
||||
fn SetX(self, value: f64);
|
||||
fn SetY(self, value: f64);
|
||||
fn SetZ(self, value: f64);
|
||||
fn SetW(self, value: f64);
|
||||
fn SetX(&self, value: f64);
|
||||
fn SetY(&self, value: f64);
|
||||
fn SetZ(&self, value: f64);
|
||||
fn SetW(&self, value: f64);
|
||||
}
|
||||
|
||||
impl<'a> DOMPointWriteMethods for &'a DOMPointReadOnly {
|
||||
fn SetX(self, value: f64) {
|
||||
impl DOMPointWriteMethods for DOMPointReadOnly {
|
||||
fn SetX(&self, value: f64) {
|
||||
self.x.set(value);
|
||||
}
|
||||
|
||||
fn SetY(self, value: f64) {
|
||||
fn SetY(&self, value: f64) {
|
||||
self.y.set(value);
|
||||
}
|
||||
|
||||
fn SetZ(self, value: f64) {
|
||||
fn SetZ(&self, value: f64) {
|
||||
self.z.set(value);
|
||||
}
|
||||
|
||||
fn SetW(self, value: f64) {
|
||||
fn SetW(&self, value: f64) {
|
||||
self.w.set(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ use dom::window::Window;
|
|||
use util::geometry::Au;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMRect {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn Top(self) -> Finite<f32> {
|
||||
fn Top(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.top)
|
||||
}
|
||||
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom
|
||||
fn Bottom(self) -> Finite<f32> {
|
||||
fn Bottom(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.bottom)
|
||||
}
|
||||
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left
|
||||
fn Left(self) -> Finite<f32> {
|
||||
fn Left(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.left)
|
||||
}
|
||||
|
||||
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right
|
||||
fn Right(self) -> Finite<f32> {
|
||||
fn Right(&self) -> Finite<f32> {
|
||||
Finite::wrap(self.right)
|
||||
}
|
||||
|
||||
// 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();
|
||||
Finite::wrap(result)
|
||||
}
|
||||
|
||||
// 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();
|
||||
Finite::wrap(result)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use dom::domrect::DOMRect;
|
|||
use dom::window::Window;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMRectList {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn Length(self) -> u32 {
|
||||
fn Length(&self) -> u32 {
|
||||
self.rects.len() as u32
|
||||
}
|
||||
|
||||
// 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;
|
||||
if index < rects.len() as u32 {
|
||||
Some(rects[index as usize].root())
|
||||
|
@ -50,9 +49,8 @@ impl<'a> DOMRectListMethods for &'a DOMRectList {
|
|||
}
|
||||
|
||||
// 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;
|
||||
self.Item(index)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,11 @@ use dom::bindings::error::ErrorResult;
|
|||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementCustomAttributeHelpers};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::window_from_node;
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMStringMap {
|
||||
reflector_: Reflector,
|
||||
element: JS<HTMLElement>,
|
||||
|
@ -35,26 +34,26 @@ impl 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
|
||||
fn NamedCreator(self, name: DOMString, value: DOMString) -> ErrorResult {
|
||||
fn NamedCreator(&self, name: DOMString, value: DOMString) -> ErrorResult {
|
||||
self.NamedSetter(name, value)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem
|
||||
fn NamedDeleter(self, name: DOMString) {
|
||||
fn NamedDeleter(&self, name: DOMString) {
|
||||
let element = self.element.root();
|
||||
element.r().delete_custom_attr(name)
|
||||
}
|
||||
|
||||
// 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();
|
||||
element.r().set_custom_attr(name, value)
|
||||
}
|
||||
|
||||
// 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();
|
||||
match element.r().get_custom_attr(name) {
|
||||
Some(value) => {
|
||||
|
@ -69,7 +68,7 @@ impl<'a> DOMStringMapMethods for &'a 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)
|
||||
vec![]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::attr::{Attr, AttrHelpers};
|
||||
use dom::attr::Attr;
|
||||
use dom::bindings::codegen::Bindings::DOMTokenListBinding;
|
||||
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods;
|
||||
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::js::{JS, Root};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::element::{Element, AttributeHandlers};
|
||||
use dom::element::Element;
|
||||
use dom::node::window_from_node;
|
||||
|
||||
use string_cache::Atom;
|
||||
|
@ -19,7 +19,6 @@ use util::str::{DOMString, HTML_SPACE_CHARACTERS, str_join};
|
|||
use std::borrow::ToOwned;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DOMTokenList {
|
||||
reflector_: Reflector,
|
||||
element: JS<Element>,
|
||||
|
@ -41,20 +40,13 @@ impl DOMTokenList {
|
|||
GlobalRef::Window(window.r()),
|
||||
DOMTokenListBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
trait PrivateDOMTokenListHelpers {
|
||||
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>> {
|
||||
fn attribute(&self) -> Option<Root<Attr>> {
|
||||
let element = self.element.root();
|
||||
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 {
|
||||
"" => Err(Syntax),
|
||||
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
|
||||
impl<'a> DOMTokenListMethods for &'a DOMTokenList {
|
||||
impl DOMTokenListMethods for DOMTokenList {
|
||||
// https://dom.spec.whatwg.org/#dom-domtokenlist-length
|
||||
fn Length(self) -> u32 {
|
||||
fn Length(&self) -> u32 {
|
||||
self.attribute().map(|attr| {
|
||||
let attr = attr.r();
|
||||
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
|
||||
fn Item(self, index: u32) -> Option<DOMString> {
|
||||
fn Item(&self, index: u32) -> Option<DOMString> {
|
||||
self.attribute().and_then(|attr| {
|
||||
let attr = attr.r();
|
||||
attr.value().tokens().and_then(|tokens| {
|
||||
|
@ -84,7 +76,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
|
|||
}
|
||||
|
||||
// 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.attribute().map(|attr| {
|
||||
let attr = attr.r();
|
||||
|
@ -98,7 +90,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
|
|||
}
|
||||
|
||||
// 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 mut atoms = element.r().get_tokenlist_attribute(&self.local_name);
|
||||
for token in &tokens {
|
||||
|
@ -112,7 +104,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
|
|||
}
|
||||
|
||||
// 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 mut atoms = element.r().get_tokenlist_attribute(&self.local_name);
|
||||
for token in &tokens {
|
||||
|
@ -126,7 +118,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
|
|||
}
|
||||
|
||||
// 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 mut atoms = element.r().get_tokenlist_attribute(&self.local_name);
|
||||
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
|
||||
fn Stringifier(self) -> DOMString {
|
||||
fn Stringifier(&self) -> DOMString {
|
||||
let tokenlist = self.element.root().r().get_tokenlist_attribute(&self.local_name);
|
||||
str_join(&tokenlist, "\x20")
|
||||
}
|
||||
|
||||
// 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);
|
||||
*found = item.is_some();
|
||||
item
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use dom::activation::Activatable;
|
||||
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::codegen::Bindings::AttrBinding::AttrMethods;
|
||||
use dom::bindings::codegen::Bindings::ElementBinding;
|
||||
|
@ -35,27 +35,26 @@ use dom::bindings::js::{Root, RootedReference};
|
|||
use dom::bindings::trace::RootedVec;
|
||||
use dom::bindings::utils::XMLName::InvalidXMLName;
|
||||
use dom::bindings::utils::{namespace_from_domstring, xml_name_type, validate_and_extract};
|
||||
use dom::characterdata::CharacterDataHelpers;
|
||||
use dom::create::create_element;
|
||||
use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers};
|
||||
use dom::document::{Document, LayoutDocumentHelpers};
|
||||
use dom::domrect::DOMRect;
|
||||
use dom::domrectlist::DOMRectList;
|
||||
use dom::domtokenlist::DOMTokenList;
|
||||
use dom::event::{Event, EventHelpers};
|
||||
use dom::event::Event;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers};
|
||||
use dom::htmlbodyelement::HTMLBodyElement;
|
||||
use dom::htmlcollection::HTMLCollection;
|
||||
use dom::htmlelement::HTMLElementTypeId;
|
||||
use dom::htmlfontelement::{HTMLFontElement, HTMLFontElementHelpers};
|
||||
use dom::htmliframeelement::{HTMLIFrameElement, RawHTMLIFrameElementHelpers};
|
||||
use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers, HTMLInputElementHelpers};
|
||||
use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementHelpers};
|
||||
use dom::htmltableelement::{HTMLTableElement, HTMLTableElementHelpers};
|
||||
use dom::htmltablerowelement::{HTMLTableRowElement, HTMLTableRowElementHelpers};
|
||||
use dom::htmltablesectionelement::{HTMLTableSectionElement, HTMLTableSectionElementHelpers};
|
||||
use dom::htmlfontelement::HTMLFontElement;
|
||||
use dom::htmliframeelement::HTMLIFrameElement;
|
||||
use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers};
|
||||
use dom::htmltablecellelement::HTMLTableCellElement;
|
||||
use dom::htmltableelement::HTMLTableElement;
|
||||
use dom::htmltablerowelement::HTMLTableRowElement;
|
||||
use dom::htmltablesectionelement::HTMLTableSectionElement;
|
||||
use dom::htmltextareaelement::{HTMLTextAreaElement, RawLayoutHTMLTextAreaElementHelpers};
|
||||
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::{window_from_node};
|
||||
use dom::nodelist::NodeList;
|
||||
|
@ -92,7 +91,6 @@ use std::mem;
|
|||
use std::sync::Arc;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Element {
|
||||
node: Node,
|
||||
local_name: Atom,
|
||||
|
@ -571,38 +569,18 @@ pub enum StylePriority {
|
|||
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 {
|
||||
fn html_element_in_html_document(self) -> bool {
|
||||
impl Element {
|
||||
pub fn html_element_in_html_document(&self) -> bool {
|
||||
let node = NodeCast::from_ref(self);
|
||||
self.namespace == ns!(HTML) && node.is_in_html_doc()
|
||||
}
|
||||
|
||||
fn local_name(self) -> &'a Atom {
|
||||
pub fn local_name(&self) -> &Atom {
|
||||
&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() {
|
||||
Atom::from_slice(&name.to_ascii_lowercase())
|
||||
} else {
|
||||
|
@ -610,27 +588,27 @@ impl<'a> ElementHelpers<'a> for &'a Element {
|
|||
}
|
||||
}
|
||||
|
||||
fn namespace(self) -> &'a Namespace {
|
||||
pub fn namespace(&self) -> &Namespace {
|
||||
&self.namespace
|
||||
}
|
||||
|
||||
fn prefix(self) -> &'a Option<DOMString> {
|
||||
pub fn prefix(&self) -> &Option<DOMString> {
|
||||
&self.prefix
|
||||
}
|
||||
|
||||
fn attrs(&self) -> Ref<Vec<JS<Attr>>> {
|
||||
pub fn attrs(&self) -> Ref<Vec<JS<Attr>>> {
|
||||
self.attrs.borrow()
|
||||
}
|
||||
|
||||
fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>> {
|
||||
pub fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>> {
|
||||
self.attrs.borrow_mut()
|
||||
}
|
||||
|
||||
fn style_attribute(self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>> {
|
||||
pub fn style_attribute(&self) -> &DOMRefCell<Option<PropertyDeclarationBlock>> {
|
||||
&self.style_attribute
|
||||
}
|
||||
|
||||
fn summarize(self) -> Vec<AttrInfo> {
|
||||
pub fn summarize(&self) -> Vec<AttrInfo> {
|
||||
let attrs = self.Attributes();
|
||||
let mut summarized = vec!();
|
||||
for i in 0..attrs.r().Length() {
|
||||
|
@ -640,7 +618,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
|
|||
summarized
|
||||
}
|
||||
|
||||
fn is_void(self) -> bool {
|
||||
pub fn is_void(&self) -> bool {
|
||||
if self.namespace != ns!(HTML) {
|
||||
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();
|
||||
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
|
||||
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();
|
||||
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
|
||||
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();
|
||||
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
|
||||
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| {
|
||||
inline_declarations.as_ref().and_then(|declarations| {
|
||||
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| {
|
||||
inline_declarations.as_ref().and_then(|declarations| {
|
||||
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 mut writer = vec![];
|
||||
match serialize(&mut writer, &node,
|
||||
|
@ -769,7 +748,7 @@ impl<'a> ElementHelpers<'a> for &'a 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);
|
||||
node.inclusive_ancestors()
|
||||
.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
|
||||
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() {
|
||||
match ElementCast::to_ref(node.r()) {
|
||||
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
|
||||
fn is_actually_disabled(self) -> bool;
|
||||
}
|
||||
|
||||
impl<'a> FocusElementHelpers for &'a Element {
|
||||
fn is_focusable_area(self) -> bool {
|
||||
impl Element {
|
||||
pub fn is_focusable_area(&self) -> bool {
|
||||
if self.is_actually_disabled() {
|
||||
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);
|
||||
match node.type_id() {
|
||||
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
|
||||
/// name, if any.
|
||||
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>> {
|
||||
impl Element {
|
||||
pub fn get_attribute(&self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
|
||||
let mut attributes = RootedVec::new();
|
||||
self.get_attributes(local_name, &mut attributes);
|
||||
attributes.r().iter()
|
||||
|
@ -915,14 +838,14 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
}
|
||||
|
||||
// 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);
|
||||
self.attrs.borrow().iter().map(|attr| attr.root())
|
||||
.find(|a| a.r().name() == 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() {
|
||||
let attr = attr.root();
|
||||
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,
|
||||
value: DOMString,
|
||||
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)
|
||||
}
|
||||
|
||||
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.contains(":"));
|
||||
|
||||
|
@ -961,7 +884,7 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
}
|
||||
|
||||
// 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.
|
||||
match xml_name_type(&name) {
|
||||
InvalidXMLName => return Err(InvalidCharacter),
|
||||
|
@ -977,7 +900,7 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn do_set_attribute<F>(self,
|
||||
pub fn do_set_attribute<F>(&self,
|
||||
local_name: Atom,
|
||||
value: AttrValue,
|
||||
name: Atom,
|
||||
|
@ -1003,7 +926,7 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
(*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 {
|
||||
if *namespace == ns!("") {
|
||||
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>> {
|
||||
self.do_remove_attribute(|attr| {
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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 node = NodeCast::from_ref(self);
|
||||
let owner_doc = node.owner_doc();
|
||||
|
@ -1074,20 +997,20 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
}).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());
|
||||
let value = AttrValue::from_atomic(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));
|
||||
self.attrs.borrow().iter().map(|attr| attr.root()).any(|attr| {
|
||||
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 value {
|
||||
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());
|
||||
if !self.has_attribute(local_name) {
|
||||
return "".to_owned();
|
||||
|
@ -1111,22 +1034,22 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
Some(x) => x.r().Value(),
|
||||
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());
|
||||
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| {
|
||||
attr.r()
|
||||
.value()
|
||||
|
@ -1136,17 +1059,17 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
}).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());
|
||||
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());
|
||||
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| {
|
||||
!ch.is_ascii() || ch.to_ascii_lowercase() == ch
|
||||
}));
|
||||
|
@ -1162,30 +1085,30 @@ impl<'a> AttributeHandlers for &'a Element {
|
|||
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());
|
||||
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
|
||||
fn GetNamespaceURI(self) -> Option<DOMString> {
|
||||
fn GetNamespaceURI(&self) -> Option<DOMString> {
|
||||
Node::namespace_to_string(self.namespace.clone())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-localname
|
||||
fn LocalName(self) -> DOMString {
|
||||
fn LocalName(&self) -> DOMString {
|
||||
(*self.local_name).to_owned()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-prefix
|
||||
fn GetPrefix(self) -> Option<DOMString> {
|
||||
fn GetPrefix(&self) -> Option<DOMString> {
|
||||
self.prefix.clone()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-tagname
|
||||
fn TagName(self) -> DOMString {
|
||||
fn TagName(&self) -> DOMString {
|
||||
let qualified_name = match self.prefix {
|
||||
Some(ref prefix) => {
|
||||
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
|
||||
fn Id(self) -> DOMString {
|
||||
fn Id(&self) -> DOMString {
|
||||
self.get_string_attribute(&atom!("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);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-classname
|
||||
fn ClassName(self) -> DOMString {
|
||||
fn ClassName(&self) -> DOMString {
|
||||
self.get_string_attribute(&atom!("class"))
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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")))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-attributes
|
||||
fn Attributes(self) -> Root<NamedNodeMap> {
|
||||
fn Attributes(&self) -> Root<NamedNodeMap> {
|
||||
self.attr_list.or_init(|| {
|
||||
let doc = {
|
||||
let node = NodeCast::from_ref(self);
|
||||
|
@ -1237,13 +1160,13 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// 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)
|
||||
.map(|s| s.r().Value())
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getattributens
|
||||
fn GetAttributeNS(self,
|
||||
fn GetAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) -> Option<DOMString> {
|
||||
let namespace = &namespace_from_domstring(namespace);
|
||||
|
@ -1252,7 +1175,7 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-setattribute
|
||||
fn SetAttribute(self,
|
||||
fn SetAttribute(&self,
|
||||
name: DOMString,
|
||||
value: DOMString) -> ErrorResult {
|
||||
// Step 1.
|
||||
|
@ -1272,7 +1195,7 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-setattributens
|
||||
fn SetAttributeNS(self,
|
||||
fn SetAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
qualified_name: DOMString,
|
||||
value: DOMString) -> ErrorResult {
|
||||
|
@ -1289,13 +1212,13 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-removeattribute
|
||||
fn RemoveAttribute(self, name: DOMString) {
|
||||
fn RemoveAttribute(&self, name: DOMString) {
|
||||
let name = self.parsed_name(name);
|
||||
self.remove_attribute_by_name(&name);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-removeattributens
|
||||
fn RemoveAttributeNS(self,
|
||||
fn RemoveAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) {
|
||||
let namespace = namespace_from_domstring(namespace);
|
||||
|
@ -1304,38 +1227,38 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-hasattributens
|
||||
fn HasAttributeNS(self,
|
||||
fn HasAttributeNS(&self,
|
||||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) -> bool {
|
||||
self.GetAttributeNS(namespace, local_name).is_some()
|
||||
}
|
||||
|
||||
// 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);
|
||||
HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), localname)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens
|
||||
fn GetElementsByTagNameNS(self, maybe_ns: Option<DOMString>,
|
||||
fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>,
|
||||
localname: DOMString) -> Root<HTMLCollection> {
|
||||
let window = window_from_node(self);
|
||||
HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), localname, maybe_ns)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname
|
||||
fn GetElementsByClassName(self, classes: DOMString) -> Root<HTMLCollection> {
|
||||
fn GetElementsByClassName(&self, classes: DOMString) -> Root<HTMLCollection> {
|
||||
let window = window_from_node(self);
|
||||
HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes)
|
||||
}
|
||||
|
||||
// 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 node = NodeCast::from_ref(self);
|
||||
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
|
||||
fn GetBoundingClientRect(self) -> Root<DOMRect> {
|
||||
fn GetBoundingClientRect(&self) -> Root<DOMRect> {
|
||||
let win = window_from_node(self);
|
||||
let node = NodeCast::from_ref(self);
|
||||
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
|
||||
fn ClientTop(self) -> i32 {
|
||||
fn ClientTop(&self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.get_client_rect().origin.y
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-clientleft
|
||||
fn ClientLeft(self) -> i32 {
|
||||
fn ClientLeft(&self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.get_client_rect().origin.x
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-clientwidth
|
||||
fn ClientWidth(self) -> i32 {
|
||||
fn ClientWidth(&self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.get_client_rect().size.width
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-clientheight
|
||||
fn ClientHeight(self) -> i32 {
|
||||
fn ClientHeight(&self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.get_client_rect().size.height
|
||||
}
|
||||
|
||||
// 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
|
||||
self.serialize(ChildrenOnly)
|
||||
}
|
||||
|
||||
// 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);
|
||||
// Step 1.
|
||||
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
|
||||
fn GetOuterHTML(self) -> Fallible<DOMString> {
|
||||
fn GetOuterHTML(&self) -> Fallible<DOMString> {
|
||||
self.serialize(IncludeNode)
|
||||
}
|
||||
|
||||
// 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_node = NodeCast::from_ref(self);
|
||||
// Step 1.
|
||||
|
@ -1441,83 +1364,83 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// 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()
|
||||
.filter_map(ElementCast::to_root).next()
|
||||
}
|
||||
|
||||
// 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()
|
||||
.filter_map(ElementCast::to_root).next()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-children
|
||||
fn Children(self) -> Root<HTMLCollection> {
|
||||
fn Children(&self) -> Root<HTMLCollection> {
|
||||
let window = window_from_node(self);
|
||||
HTMLCollection::children(window.r(), NodeCast::from_ref(self))
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
|
||||
fn GetFirstElementChild(self) -> Option<Root<Element>> {
|
||||
fn GetFirstElementChild(&self) -> Option<Root<Element>> {
|
||||
NodeCast::from_ref(self).child_elements().next()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
|
||||
fn GetLastElementChild(self) -> Option<Root<Element>> {
|
||||
fn GetLastElementChild(&self) -> Option<Root<Element>> {
|
||||
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
|
||||
fn ChildElementCount(self) -> u32 {
|
||||
fn ChildElementCount(&self) -> u32 {
|
||||
NodeCast::from_ref(self).child_elements().count() as u32
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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);
|
||||
root.query_selector(selectors)
|
||||
}
|
||||
|
||||
// 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);
|
||||
root.query_selector_all(selectors)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-childnode-remove
|
||||
fn Remove(self) {
|
||||
fn Remove(&self) {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.remove_self();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
Err(()) => Err(Syntax),
|
||||
Ok(ref selectors) => {
|
||||
|
@ -1527,7 +1450,7 @@ impl<'a> ElementMethods for &'a Element {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
Err(()) => Err(Syntax),
|
||||
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> {
|
||||
let node: &&Node = NodeCast::from_borrowed_ref(self);
|
||||
let node: &Node = NodeCast::from_ref(self);
|
||||
Some(node as &VirtualMethods)
|
||||
}
|
||||
|
||||
|
@ -1556,11 +1479,11 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
s.after_set_attr(attr);
|
||||
}
|
||||
|
||||
let node = NodeCast::from_ref(*self);
|
||||
let node = NodeCast::from_ref(self);
|
||||
match attr.local_name() {
|
||||
&atom!("style") => {
|
||||
// Modifying the `style` attribute might change style.
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
let base_url = doc.r().base_url();
|
||||
let value = attr.value();
|
||||
let style = Some(parse_style_attribute(&value, &base_url));
|
||||
|
@ -1573,7 +1496,7 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
&atom!("class") => {
|
||||
// Modifying a class can change style.
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(*self);
|
||||
let document = document_from_node(self);
|
||||
document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
|
@ -1581,10 +1504,10 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
// Modifying an ID might change style.
|
||||
let value = attr.value();
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
if !value.is_empty() {
|
||||
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);
|
||||
}
|
||||
|
@ -1592,7 +1515,7 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
_ => {
|
||||
// Modifying any other attribute might change arbitrary things.
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(*self);
|
||||
let document = document_from_node(self);
|
||||
document.r().content_changed(node, NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
|
@ -1604,14 +1527,14 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
s.before_remove_attr(attr);
|
||||
}
|
||||
|
||||
let node = NodeCast::from_ref(*self);
|
||||
let node = NodeCast::from_ref(self);
|
||||
match attr.local_name() {
|
||||
&atom!("style") => {
|
||||
// Modifying the `style` attribute might change style.
|
||||
*self.style_attribute.borrow_mut() = None;
|
||||
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
doc.r().content_changed(node, NodeDamage::NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
|
@ -1619,10 +1542,10 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
// Modifying an ID can change style.
|
||||
let value = attr.value();
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
if !value.is_empty() {
|
||||
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);
|
||||
}
|
||||
|
@ -1630,14 +1553,14 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
&atom!("class") => {
|
||||
// Modifying a class can change style.
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(*self);
|
||||
let document = document_from_node(self);
|
||||
document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Modifying any other attribute might change arbitrary things.
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
doc.r().content_changed(node, NodeDamage::OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
|
@ -1660,11 +1583,11 @@ impl<'a> VirtualMethods for &'a Element {
|
|||
if !tree_in_doc { return; }
|
||||
|
||||
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();
|
||||
if !value.is_empty() {
|
||||
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 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();
|
||||
if !value.is_empty() {
|
||||
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 {
|
||||
ElementHelpers::local_name(&**self)
|
||||
self.local_name()
|
||||
}
|
||||
fn get_namespace<'b>(&'b self) -> &'b Namespace {
|
||||
self.namespace()
|
||||
|
@ -1798,7 +1721,7 @@ impl<'a> ::selectors::Element for Root<Element> {
|
|||
}
|
||||
}
|
||||
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)
|
||||
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 {
|
||||
fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)> {
|
||||
let node = NodeCast::from_ref(*self);
|
||||
impl Element {
|
||||
pub fn as_maybe_activatable<'a>(&'a self) -> Option<&'a (Activatable + 'a)> {
|
||||
let node = NodeCast::from_ref(self);
|
||||
let element = match node.type_id() {
|
||||
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))
|
||||
},
|
||||
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))
|
||||
},
|
||||
_ => {
|
||||
|
@ -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);
|
||||
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);
|
||||
node.set_flag(CLICK_IN_PROGRESS, click)
|
||||
}
|
||||
|
||||
// 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() {
|
||||
Some(el) => Some(Root::from_ref(el.as_element())),
|
||||
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.
|
||||
/// 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
|
||||
// required to save state between pre-activation and post-activation
|
||||
// since we cannot nest authentic clicks (unlike synthetic click activation, where
|
||||
|
@ -1953,10 +1869,10 @@ impl<'a> ActivationElementHelpers<'a> for &'a Element {
|
|||
}
|
||||
}
|
||||
// Step 6
|
||||
None => {event.fire(target);}
|
||||
None => { event.fire(target); }
|
||||
},
|
||||
// Step 6
|
||||
None => {event.fire(target);}
|
||||
None => { event.fire(target); }
|
||||
}
|
||||
// Step 7
|
||||
self.set_click_in_progress(false);
|
||||
|
|
|
@ -22,7 +22,6 @@ use std::borrow::ToOwned;
|
|||
use std::cell::Cell;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct ErrorEvent {
|
||||
event: Event,
|
||||
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
|
||||
fn Lineno(self) -> u32 {
|
||||
fn Lineno(&self) -> u32 {
|
||||
self.lineno.get()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-errorevent-colno
|
||||
fn Colno(self) -> u32 {
|
||||
fn Colno(&self) -> u32 {
|
||||
self.colno.get()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-errorevent-message
|
||||
fn Message(self) -> DOMString {
|
||||
fn Message(&self) -> DOMString {
|
||||
self.message.borrow().clone()
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-errorevent-filename
|
||||
fn Filename(self) -> DOMString {
|
||||
fn Filename(&self) -> DOMString {
|
||||
self.filename.borrow().clone()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::error::Fallible;
|
|||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
||||
use dom::bindings::utils::{Reflector, reflect_dom_object};
|
||||
use dom::eventtarget::{EventTarget, EventTargetHelpers};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::uievent::{UIEventTypeId};
|
||||
use util::str::DOMString;
|
||||
|
||||
|
@ -54,7 +54,6 @@ pub enum EventCancelable {
|
|||
}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct Event {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn EventPhase(self) -> u16 {
|
||||
fn EventPhase(&self) -> u16 {
|
||||
self.phase.get() as u16
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-type
|
||||
fn Type(self) -> DOMString {
|
||||
fn Type(&self) -> DOMString {
|
||||
self.type_.borrow().clone()
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-defaultprevented
|
||||
fn DefaultPrevented(self) -> bool {
|
||||
fn DefaultPrevented(&self) -> bool {
|
||||
self.canceled.get()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-preventdefault
|
||||
fn PreventDefault(self) {
|
||||
fn PreventDefault(&self) {
|
||||
if self.cancelable.get() {
|
||||
self.canceled.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-stoppropagation
|
||||
fn StopPropagation(self) {
|
||||
fn StopPropagation(&self) {
|
||||
self.stop_propagation.set(true);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation
|
||||
fn StopImmediatePropagation(self) {
|
||||
fn StopImmediatePropagation(&self) {
|
||||
self.stop_immediate.set(true);
|
||||
self.stop_propagation.set(true);
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-bubbles
|
||||
fn Bubbles(self) -> bool {
|
||||
fn Bubbles(&self) -> bool {
|
||||
self.bubbles.get()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-cancelable
|
||||
fn Cancelable(self) -> bool {
|
||||
fn Cancelable(&self) -> bool {
|
||||
self.cancelable.get()
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-timestamp
|
||||
fn TimeStamp(self) -> u64 {
|
||||
fn TimeStamp(&self) -> u64 {
|
||||
self.timestamp
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-initevent
|
||||
fn InitEvent(self,
|
||||
fn InitEvent(&self,
|
||||
type_: DOMString,
|
||||
bubbles: bool,
|
||||
cancelable: bool) {
|
||||
|
@ -253,23 +252,19 @@ impl<'a> EventMethods for &'a Event {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-event-istrusted
|
||||
fn IsTrusted(self) -> bool {
|
||||
fn IsTrusted(&self) -> bool {
|
||||
self.trusted.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EventHelpers {
|
||||
fn set_trusted(self, trusted: bool);
|
||||
fn fire(self, target: &EventTarget) -> bool;
|
||||
}
|
||||
|
||||
impl<'a> EventHelpers for &'a Event {
|
||||
fn set_trusted(self, trusted: bool) {
|
||||
impl Event {
|
||||
pub fn set_trusted(&self, trusted: bool) {
|
||||
self.trusted.set(trusted);
|
||||
}
|
||||
|
||||
// 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);
|
||||
target.dispatch_event(self)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use dom::bindings::js::JS;
|
|||
use dom::bindings::trace::RootedVec;
|
||||
use dom::event::{Event, EventPhase};
|
||||
use dom::eventtarget::{EventTarget, ListenerPhase};
|
||||
use dom::node::{Node, NodeHelpers};
|
||||
use dom::node::Node;
|
||||
use dom::virtualmethods::vtable_for;
|
||||
|
||||
// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
|
||||
|
|
|
@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
|
|||
use dom::bindings::error::Error::InvalidState;
|
||||
use dom::bindings::error::{Fallible, report_pending_exception};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::event::{Event, EventHelpers};
|
||||
use dom::event::Event;
|
||||
use dom::eventdispatcher::dispatch_event;
|
||||
use dom::node::NodeTypeId;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
|
@ -130,7 +130,6 @@ pub struct EventListenerEntry {
|
|||
}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct EventTarget {
|
||||
reflector_: Reflector,
|
||||
type_id: EventTargetTypeId,
|
||||
|
@ -164,42 +163,18 @@ impl EventTarget {
|
|||
pub fn type_id<'a>(&'a self) -> &'a EventTargetTypeId {
|
||||
&self.type_id
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EventTargetHelpers {
|
||||
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,
|
||||
pub fn dispatch_event_with_target(&self,
|
||||
target: &EventTarget,
|
||||
event: &Event) -> bool {
|
||||
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)
|
||||
}
|
||||
|
||||
fn set_inline_event_listener(self,
|
||||
pub fn set_inline_event_listener(&self,
|
||||
ty: DOMString,
|
||||
listener: Option<Rc<EventHandler>>) {
|
||||
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 entries = handlers.get(&ty);
|
||||
entries.and_then(|entries| entries.iter().filter_map(|entry| {
|
||||
|
@ -247,7 +222,7 @@ impl<'a> EventTargetHelpers for &'a EventTarget {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn set_event_handler_uncompiled(self,
|
||||
pub fn set_event_handler_uncompiled(&self,
|
||||
cx: *mut JSContext,
|
||||
url: Url,
|
||||
scope: HandleObject,
|
||||
|
@ -288,27 +263,27 @@ impl<'a> EventTargetHelpers for &'a EventTarget {
|
|||
self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj)));
|
||||
}
|
||||
|
||||
fn set_event_handler_common<T: CallbackContainer>(
|
||||
self, ty: &str, listener: Option<Rc<T>>)
|
||||
pub fn set_event_handler_common<T: CallbackContainer>(
|
||||
&self, ty: &str, listener: Option<Rc<T>>)
|
||||
{
|
||||
let event_listener = listener.map(|listener|
|
||||
EventHandlerNonNull::new(listener.callback()));
|
||||
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());
|
||||
listener.map(|listener| CallbackContainer::new(listener.parent.callback()))
|
||||
}
|
||||
|
||||
fn has_handlers(self) -> bool {
|
||||
pub fn has_handlers(&self) -> bool {
|
||||
!self.handlers.borrow().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EventTargetMethods for &'a EventTarget {
|
||||
impl EventTargetMethods for EventTarget {
|
||||
// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener
|
||||
fn AddEventListener(self,
|
||||
fn AddEventListener(&self,
|
||||
ty: DOMString,
|
||||
listener: Option<Rc<EventListener>>,
|
||||
capture: bool) {
|
||||
|
@ -334,7 +309,7 @@ impl<'a> EventTargetMethods for &'a EventTarget {
|
|||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener
|
||||
fn RemoveEventListener(self,
|
||||
fn RemoveEventListener(&self,
|
||||
ty: DOMString,
|
||||
listener: Option<Rc<EventListener>>,
|
||||
capture: bool) {
|
||||
|
@ -358,7 +333,7 @@ impl<'a> EventTargetMethods for &'a EventTarget {
|
|||
}
|
||||
|
||||
// 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() {
|
||||
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> {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ use dom::blob::{Blob, BlobTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct File {
|
||||
blob: Blob,
|
||||
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
|
||||
fn Name(self) -> DOMString {
|
||||
fn Name(&self) -> DOMString {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ use dom::window::Window;
|
|||
|
||||
// https://w3c.github.io/FileAPI/#dfn-filelist
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct FileList {
|
||||
reflector_: Reflector,
|
||||
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
|
||||
fn Length(self) -> u32 {
|
||||
fn Length(&self) -> u32 {
|
||||
self.list.len() as u32
|
||||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
|
||||
// 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);
|
||||
*found = item.is_some();
|
||||
item
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,16 +12,17 @@ use dom::bindings::global::{GlobalRef, GlobalField};
|
|||
use dom::bindings::js::{Root, JS, MutNullableHeap};
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::utils::{reflect_dom_object, Reflectable};
|
||||
use dom::blob::{Blob, BlobHelpers};
|
||||
use dom::blob::Blob;
|
||||
use dom::domexception::{DOMException, DOMErrorName};
|
||||
use dom::event::{EventHelpers, EventCancelable, EventBubbles};
|
||||
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
||||
use dom::event::{EventCancelable, EventBubbles};
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::progressevent::ProgressEvent;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::label::encoding_from_whatwg_label;
|
||||
use encoding::types::{EncodingRef, DecoderTrap};
|
||||
use hyper::mime::{Mime, Attr};
|
||||
use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
|
||||
use script_task::ScriptTaskEventCategory::FileRead;
|
||||
use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::sync::mpsc;
|
||||
|
@ -67,7 +68,6 @@ pub enum FileReaderReadyState {
|
|||
}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct FileReader {
|
||||
eventtarget: EventTarget,
|
||||
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);
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-onprogress
|
||||
event_handler!(progress, GetOnprogress, SetOnprogress);
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-onload
|
||||
event_handler!(load, GetOnload, SetOnload);
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-onabort
|
||||
event_handler!(abort, GetOnabort, SetOnabort);
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-onerror
|
||||
event_handler!(error, GetOnerror, SetOnerror);
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-onloadend
|
||||
event_handler!(loadend, GetOnloadend, SetOnloadend);
|
||||
|
||||
//TODO https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-abort
|
||||
fn Abort(self) {
|
||||
fn Abort(&self) {
|
||||
// Step 2
|
||||
if self.ready_state.get() == FileReaderReadyState::Loading {
|
||||
self.change_ready_state(FileReaderReadyState::Done);
|
||||
|
@ -291,30 +302,24 @@ impl<'a> FileReaderMethods for &'a FileReader {
|
|||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-result
|
||||
fn GetResult(self) -> Option<DOMString> {
|
||||
fn GetResult(&self) -> Option<DOMString> {
|
||||
self.result.borrow().clone()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/FileAPI/#dfn-readyState
|
||||
fn ReadyState(self) -> u16 {
|
||||
fn ReadyState(&self) -> 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 {
|
||||
fn dispatch_progress_event(self, type_: DOMString, loaded: u64, total: Option<u64>) {
|
||||
impl FileReader {
|
||||
fn dispatch_progress_event(&self, type_: DOMString, loaded: u64, total: Option<u64>) {
|
||||
|
||||
let global = self.global.root();
|
||||
let progressevent = ProgressEvent::new(global.r(),
|
||||
|
@ -326,12 +331,12 @@ impl<'a> PrivateFileReaderHelpers for &'a FileReader {
|
|||
event.fire(target);
|
||||
}
|
||||
|
||||
fn terminate_ongoing_reading(self) {
|
||||
fn terminate_ongoing_reading(&self) {
|
||||
let GenerationId(prev_id) = self.generation_id.get();
|
||||
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 global = root.r();
|
||||
// Step 1
|
||||
|
@ -369,7 +374,7 @@ impl<'a> PrivateFileReaderHelpers for &'a FileReader {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn change_ready_state(self, state: FileReaderReadyState) {
|
||||
fn change_ready_state(&self, state: FileReaderReadyState) {
|
||||
self.ready_state.set(state);
|
||||
}
|
||||
}
|
||||
|
@ -408,22 +413,22 @@ fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, bl
|
|||
let chan = &script_chan;
|
||||
// Step 4
|
||||
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(),
|
||||
gen_id, DOMString::new());
|
||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
||||
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||
|
||||
let bytes = match blob_contents.recv() {
|
||||
Ok(bytes) => bytes,
|
||||
Err(_) => {
|
||||
let task = box FileReaderEvent::ProcessReadError(filereader,
|
||||
gen_id, DOMErrorName::NotFoundError);
|
||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
||||
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes);
|
||||
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap();
|
||||
chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ pub enum FormDatum {
|
|||
}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct FormData {
|
||||
reflector_: Reflector,
|
||||
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)]
|
||||
// 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 mut data = self.data.borrow_mut();
|
||||
match data.entry(name) {
|
||||
|
@ -73,7 +72,7 @@ impl<'a> FormDataMethods for &'a FormData {
|
|||
}
|
||||
|
||||
// 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();
|
||||
match data.entry(name) {
|
||||
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
|
||||
fn Delete(self, name: DOMString) {
|
||||
fn Delete(&self, name: DOMString) {
|
||||
self.data.borrow_mut().remove(&name);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
// https://xhr.spec.whatwg.org/#dom-formdata-get
|
||||
fn Get(self, name: DOMString) -> Option<FileOrString> {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
||||
let data = self.data.borrow();
|
||||
if data.contains_key(&name) {
|
||||
match data[&name][0].clone() {
|
||||
FormDatum::StringData(ref s) => Some(eString(s.clone())),
|
||||
FormDatum::FileData(ref f) => {
|
||||
Some(eFile(f.root()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn Get(&self, name: DOMString) -> Option<FileOrString> {
|
||||
self.data.borrow()
|
||||
.get(&name)
|
||||
.map(|entry| match entry[0] {
|
||||
FormDatum::StringData(ref s) => eString(s.clone()),
|
||||
FormDatum::FileData(ref f) => eFile(f.root()),
|
||||
})
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)));
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
// 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)));
|
||||
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 {
|
||||
fn get_file_from_blob(self, value: &Blob, filename: Option<DOMString>) -> Root<File> {
|
||||
impl FormData {
|
||||
fn get_file_from_blob(&self, value: &Blob, filename: Option<DOMString>) -> Root<File> {
|
||||
let global = self.global.root();
|
||||
let f: Option<&File> = FileCast::to_ref(value);
|
||||
let name = filename.unwrap_or(f.map(|inner| inner.name().clone()).unwrap_or("blob".to_owned()));
|
||||
|
|
|
@ -14,15 +14,14 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
|
|||
use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast};
|
||||
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
||||
use dom::document::{Document, DocumentHelpers};
|
||||
use dom::document::Document;
|
||||
use dom::domtokenlist::DOMTokenList;
|
||||
use dom::element::{Element, AttributeHandlers, ElementTypeId};
|
||||
use dom::element::{Element, ElementTypeId};
|
||||
use dom::event::Event;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
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::window::WindowHelpers;
|
||||
|
||||
use util::str::DOMString;
|
||||
|
||||
|
@ -33,7 +32,6 @@ use url::UrlParser;
|
|||
use std::default::Default;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLAnchorElement {
|
||||
htmlelement: HTMLElement,
|
||||
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> {
|
||||
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
|
||||
let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
|
||||
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
|
||||
fn Text(self) -> DOMString {
|
||||
fn Text(&self) -> DOMString {
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.GetTextContent().unwrap()
|
||||
}
|
||||
|
||||
// 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);
|
||||
node.SetTextContent(Some(value))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-a-rellist
|
||||
fn RelList(self) -> Root<DOMTokenList> {
|
||||
fn RelList(&self) -> Root<DOMTokenList> {
|
||||
self.rel_list.or_init(|| {
|
||||
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 {
|
||||
ElementCast::from_ref(*self)
|
||||
ElementCast::from_ref(self)
|
||||
}
|
||||
|
||||
fn is_instance_activatable(&self) -> bool {
|
||||
|
@ -113,7 +111,7 @@ impl<'a> Activatable for &'a HTMLAnchorElement {
|
|||
// hyperlink"
|
||||
// https://html.spec.whatwg.org/multipage/#the-a-element
|
||||
// "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
|
||||
fn activation_behavior(&self, event: &Event, target: &EventTarget) {
|
||||
//Step 1. If the node document is not fully active, abort.
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
if !doc.r().is_fully_active() {
|
||||
return;
|
||||
}
|
||||
//TODO: Step 2. Check if browsing context is specified and act accordingly.
|
||||
//Step 3. Handle <img ismap/>.
|
||||
let element = ElementCast::from_ref(*self);
|
||||
let element = ElementCast::from_ref(self);
|
||||
let mouse_event = MouseEventCast::to_ref(event).unwrap();
|
||||
let mut ismap_suffix = None;
|
||||
if let Some(element) = ElementCast::to_ref(target) {
|
||||
|
|
|
@ -10,7 +10,7 @@ use dom::bindings::codegen::InheritTypes::HTMLAppletElementDerived;
|
|||
use dom::bindings::codegen::InheritTypes::HTMLElementCast;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::document::Document;
|
||||
use dom::element::{AttributeHandlers, ElementTypeId};
|
||||
use dom::element::ElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
use dom::node::{Node, NodeTypeId};
|
||||
|
@ -20,7 +20,6 @@ use string_cache::Atom;
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLAppletElement {
|
||||
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
|
||||
make_getter!(Name);
|
||||
|
||||
// https://html.spec.whatwg.org/#the-applet-element:dom-applet-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> {
|
||||
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 {
|
||||
|
|
|
@ -14,7 +14,7 @@ use dom::domtokenlist::DOMTokenList;
|
|||
use dom::element::ElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
use dom::node::{Node, NodeHelpers, NodeTypeId};
|
||||
use dom::node::{Node, NodeTypeId};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
|
||||
use std::default::Default;
|
||||
|
@ -22,7 +22,6 @@ use string_cache::Atom;
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLAreaElement {
|
||||
htmlelement: HTMLElement,
|
||||
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> {
|
||||
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
|
||||
let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
|
||||
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
|
||||
fn RelList(self) -> Root<DOMTokenList> {
|
||||
fn RelList(&self) -> Root<DOMTokenList> {
|
||||
self.rel_list.or_init(|| {
|
||||
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
|
||||
})
|
||||
|
|
|
@ -14,7 +14,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLAudioElement {
|
||||
htmlmediaelement: HTMLMediaElement
|
||||
}
|
||||
|
@ -46,4 +45,3 @@ impl HTMLAudioElement {
|
|||
Node::reflect_node(box element, document, HTMLAudioElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::attr::{Attr, AttrHelpers};
|
||||
use dom::attr::Attr;
|
||||
use dom::bindings::codegen::Bindings::HTMLBaseElementBinding;
|
||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLElementCast;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::document::{Document, DocumentHelpers};
|
||||
use dom::element::{ElementTypeId, AttributeHandlers};
|
||||
use dom::document::Document;
|
||||
use dom::element::ElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
use dom::node::{Node, NodeTypeId, document_from_node};
|
||||
|
@ -19,7 +19,6 @@ use util::str::DOMString;
|
|||
use url::{Url, UrlParser};
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLBaseElement {
|
||||
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> {
|
||||
Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods)
|
||||
Some(HTMLElementCast::from_ref(self) as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, attr: &Attr) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::attr::{Attr, AttrHelpers};
|
||||
use dom::attr::Attr;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||
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::js::Root;
|
||||
use dom::bindings::utils::Reflectable;
|
||||
use dom::document::{Document, DocumentHelpers};
|
||||
use dom::document::Document;
|
||||
use dom::element::ElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers};
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
use dom::node::{Node, NodeTypeId, window_from_node, document_from_node};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom::window::WindowHelpers;
|
||||
use msg::constellation_msg::ConstellationChan;
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
|
||||
|
@ -35,7 +34,6 @@ use time;
|
|||
const INITIAL_REFLOW_DELAY: u64 = 200_000_000;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLBodyElement {
|
||||
htmlelement: HTMLElement,
|
||||
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
|
||||
make_getter!(BgColor, "bgcolor");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage#dom-body-bgcolor
|
||||
make_setter!(SetBgColor, "bgcolor");
|
||||
|
||||
// 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);
|
||||
win.r().GetOnunload()
|
||||
}
|
||||
|
||||
// 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);
|
||||
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 {
|
||||
fn get_background_color(self) -> Option<RGBA> {
|
||||
impl HTMLBodyElement {
|
||||
pub fn get_background_color(&self) -> Option<RGBA> {
|
||||
self.background_color.get()
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn get_background(self) -> Option<Url> {
|
||||
pub fn get_background(&self) -> Option<Url> {
|
||||
unsafe {
|
||||
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> {
|
||||
let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
|
||||
let element: &HTMLElement = HTMLElementCast::from_ref(self);
|
||||
Some(element as &VirtualMethods)
|
||||
}
|
||||
|
||||
|
@ -121,7 +117,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
|
|||
return
|
||||
}
|
||||
|
||||
let window = window_from_node(*self);
|
||||
let window = window_from_node(self);
|
||||
let document = window.r().Document();
|
||||
document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
|
||||
let ConstellationChan(ref chan) = window.r().constellation_chan();
|
||||
|
@ -141,7 +137,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
|
|||
"onbeforeunload", "onhashchange", "onlanguagechange", "onmessage",
|
||||
"onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate",
|
||||
"onstorage", "onresize", "onunload", "onerror"];
|
||||
let window = window_from_node(*self);
|
||||
let window = window_from_node(self);
|
||||
let (cx, url, reflector) = (window.r().get_cx(),
|
||||
window.r().get_url(),
|
||||
window.r().reflector().get_jsobject());
|
||||
|
@ -149,7 +145,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
|
|||
if FORWARDED_EVENTS.iter().any(|&event| &**name == event) {
|
||||
EventTargetCast::from_ref(window.r())
|
||||
} else {
|
||||
EventTargetCast::from_ref(*self)
|
||||
EventTargetCast::from_ref(self)
|
||||
};
|
||||
evtarget.set_event_handler_uncompiled(cx, url, reflector,
|
||||
&name[2..],
|
||||
|
@ -161,7 +157,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
|
|||
self.background_color.set(str::parse_legacy_color(&attr.value()).ok())
|
||||
}
|
||||
&atom!("background") => {
|
||||
let doc = document_from_node(*self);
|
||||
let doc = document_from_node(self);
|
||||
let base = doc.r().url();
|
||||
|
||||
*self.background.borrow_mut() = UrlParser::new().base_url(&base).parse(&attr.value()).ok();
|
||||
|
@ -183,4 +179,3 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLBRElement {
|
||||
htmlelement: HTMLElement,
|
||||
}
|
||||
|
@ -41,4 +40,3 @@ impl HTMLBRElement {
|
|||
Node::reflect_node(box element, document, HTMLBRElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,21 +4,19 @@
|
|||
|
||||
use dom::activation::Activatable;
|
||||
use dom::attr::Attr;
|
||||
use dom::attr::AttrHelpers;
|
||||
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLButtonElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived};
|
||||
use dom::bindings::js::Root;
|
||||
use dom::document::Document;
|
||||
use dom::element::ActivationElementHelpers;
|
||||
use dom::element::{AttributeHandlers, Element, ElementTypeId};
|
||||
use dom::element::{Element, ElementTypeId};
|
||||
use dom::event::Event;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
use dom::htmlformelement::{FormSubmitter, FormControl, HTMLFormElementHelpers};
|
||||
use dom::htmlformelement::{FormSubmitter, FormControl};
|
||||
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::virtualmethods::VirtualMethods;
|
||||
|
||||
|
@ -38,7 +36,6 @@ enum ButtonType {
|
|||
}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLButtonElement {
|
||||
htmlelement: HTMLElement,
|
||||
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
|
||||
fn Validity(self) -> Root<ValidityState> {
|
||||
fn Validity(&self) -> Root<ValidityState> {
|
||||
let window = window_from_node(self);
|
||||
ValidityState::new(window.r())
|
||||
}
|
||||
|
@ -87,7 +84,7 @@ impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
|
|||
make_bool_setter!(SetDisabled, "disabled");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-button-type
|
||||
fn Type(self) -> DOMString {
|
||||
fn Type(&self) -> DOMString {
|
||||
let elem = ElementCast::from_ref(self);
|
||||
let mut ty = elem.get_string_attribute(&atom!("type"));
|
||||
ty.make_ascii_lowercase();
|
||||
|
@ -101,22 +98,29 @@ impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-button-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);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formaction
|
||||
make_setter!(SetFormAction, "formaction");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formenctype
|
||||
make_enumerated_getter!(
|
||||
FormEnctype, "application/x-www-form-urlencoded", ("text/plain") | ("multipart/form-data"));
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formenctype
|
||||
make_setter!(SetFormEnctype, "formenctype");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formmethod
|
||||
make_enumerated_getter!(FormMethod, "get", ("post") | ("dialog"));
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formmethod
|
||||
make_setter!(SetFormMethod, "formmethod");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formtarget
|
||||
make_getter!(FormTarget);
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fs-formtarget
|
||||
make_setter!(SetFormTarget, "formtarget");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-fe-name
|
||||
|
@ -132,9 +136,9 @@ impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
|
|||
make_setter!(SetValue, "value");
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for &'a HTMLButtonElement {
|
||||
impl VirtualMethods for HTMLButtonElement {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -145,7 +149,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
|
|||
|
||||
match attr.local_name() {
|
||||
&atom!("disabled") => {
|
||||
let node = NodeCast::from_ref(*self);
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.set_disabled_state(true);
|
||||
node.set_enabled_state(false);
|
||||
},
|
||||
|
@ -160,7 +164,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
|
|||
|
||||
match attr.local_name() {
|
||||
&atom!("disabled") => {
|
||||
let node = NodeCast::from_ref(*self);
|
||||
let node = NodeCast::from_ref(self);
|
||||
node.set_disabled_state(false);
|
||||
node.set_enabled_state(true);
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
|
@ -174,7 +178,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -183,7 +187,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
|
|||
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()) {
|
||||
node.check_ancestors_disabled_state_for_form_control();
|
||||
} else {
|
||||
|
@ -253,4 +257,3 @@ impl<'a> Activatable for &'a HTMLButtonElement {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::attr::Attr;
|
||||
use dom::attr::AttrHelpers;
|
||||
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
|
||||
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::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
|
||||
use dom::document::Document;
|
||||
use dom::element::AttributeHandlers;
|
||||
use dom::element::ElementTypeId;
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
|
@ -47,7 +45,6 @@ pub enum CanvasContext {
|
|||
impl HeapGCValue for CanvasContext {}
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLCanvasElement {
|
||||
htmlelement: HTMLElement,
|
||||
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<'a> HTMLCanvasElementHelpers for &'a HTMLCanvasElement {
|
||||
fn get_or_init_2d_context(self) -> Option<Root<CanvasRenderingContext2D>> {
|
||||
impl HTMLCanvasElement {
|
||||
pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> {
|
||||
if self.context.get().is_none() {
|
||||
let window = window_from_node(self);
|
||||
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,
|
||||
attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HTMLCanvasElementMethods for &'a HTMLCanvasElement {
|
||||
impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
||||
// https://html.spec.whatwg.org/multipage/#dom-canvas-width
|
||||
fn Width(self) -> u32 {
|
||||
fn Width(&self) -> u32 {
|
||||
self.width.get()
|
||||
}
|
||||
|
||||
// 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);
|
||||
elem.set_uint_attribute(&atom!("width"), width)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-canvas-height
|
||||
fn Height(self) -> u32 {
|
||||
fn Height(&self) -> u32 {
|
||||
self.height.get()
|
||||
}
|
||||
|
||||
// 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);
|
||||
elem.set_uint_attribute(&atom!("height"), height)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext
|
||||
fn GetContext(self,
|
||||
fn GetContext(&self,
|
||||
cx: *mut JSContext,
|
||||
id: DOMString,
|
||||
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> {
|
||||
let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
|
||||
let element: &HTMLElement = HTMLElementCast::from_ref(self);
|
||||
Some(element as &VirtualMethods)
|
||||
}
|
||||
|
||||
|
@ -340,4 +329,3 @@ pub mod utils {
|
|||
result.image_response
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ use dom::bindings::global::GlobalRef;
|
|||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::bindings::utils::{namespace_from_domstring, Reflector, reflect_dom_object};
|
||||
use dom::element::{Element, AttributeHandlers, ElementHelpers};
|
||||
use dom::node::{Node, NodeHelpers, TreeIterator};
|
||||
use dom::element::Element;
|
||||
use dom::node::{Node, TreeIterator};
|
||||
use dom::window::Window;
|
||||
use util::str::{DOMString, split_html_space_chars};
|
||||
|
||||
|
@ -26,7 +26,6 @@ pub trait CollectionFilter : JSTraceable {
|
|||
pub struct Collection(JS<Node>, Box<CollectionFilter + 'static>);
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLCollection {
|
||||
reflector_: Reflector,
|
||||
#[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),
|
||||
GlobalRef::Window(window), HTMLCollectionBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl HTMLCollection {
|
||||
pub fn create(window: &Window, root: &Node,
|
||||
filter: Box<CollectionFilter + 'static>) -> Root<HTMLCollection> {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
fn Length(self) -> u32 {
|
||||
fn Length(&self) -> u32 {
|
||||
self.elements_iter().count() as u32
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
if key.is_empty() {
|
||||
return None;
|
||||
|
@ -219,21 +216,21 @@ impl<'a> HTMLCollectionMethods for &'a HTMLCollection {
|
|||
}
|
||||
|
||||
// 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);
|
||||
*found = maybe_elem.is_some();
|
||||
maybe_elem
|
||||
}
|
||||
|
||||
// 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);
|
||||
*found = maybe_elem.is_some();
|
||||
maybe_elem
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-htmlcollection
|
||||
fn SupportedPropertyNames(self) -> Vec<DOMString> {
|
||||
fn SupportedPropertyNames(&self) -> Vec<DOMString> {
|
||||
// Step 1
|
||||
let mut result = vec![];
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLDataElement {
|
||||
htmlelement: HTMLElement
|
||||
}
|
||||
|
@ -43,4 +42,3 @@ impl HTMLDataElement {
|
|||
Node::reflect_node(box element, document, HTMLDataElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ use dom::node::{Node, NodeTypeId, window_from_node};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLDataListElement {
|
||||
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
|
||||
fn Options(self) -> Root<HTMLCollection> {
|
||||
fn Options(&self) -> Root<HTMLCollection> {
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
struct HTMLDataListOptionsFilter;
|
||||
impl CollectionFilter for HTMLDataListOptionsFilter {
|
||||
|
@ -65,4 +64,3 @@ impl<'a> HTMLDataListElementMethods for &'a HTMLDataListElement {
|
|||
HTMLCollection::create(window.r(), node, filter)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ use util::str::DOMString;
|
|||
use std::borrow::ToOwned;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLDialogElement {
|
||||
htmlelement: HTMLElement,
|
||||
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
|
||||
make_bool_getter!(Open);
|
||||
|
||||
|
@ -60,13 +59,13 @@ impl<'a> HTMLDialogElementMethods for &'a HTMLDialogElement {
|
|||
make_bool_setter!(SetOpen, "open");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-dialog-returnvalue
|
||||
fn ReturnValue(self) -> DOMString {
|
||||
fn ReturnValue(&self) -> DOMString {
|
||||
let return_value = self.return_value.borrow();
|
||||
return_value.clone()
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLDirectoryElement {
|
||||
htmlelement: HTMLElement
|
||||
}
|
||||
|
@ -44,4 +43,3 @@ impl HTMLDirectoryElement {
|
|||
Node::reflect_node(box element, document, HTMLDirectoryElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLDivElement {
|
||||
htmlelement: HTMLElement
|
||||
}
|
||||
|
@ -43,4 +42,3 @@ impl HTMLDivElement {
|
|||
Node::reflect_node(box element, document, HTMLDivElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLDListElement {
|
||||
htmlelement: HTMLElement
|
||||
}
|
||||
|
@ -42,4 +41,3 @@ impl HTMLDListElement {
|
|||
Node::reflect_node(box element, document, HTMLDListElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::attr::Attr;
|
||||
use dom::attr::AttrHelpers;
|
||||
use dom::attr::AttrValue;
|
||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||
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::utils::Reflectable;
|
||||
use dom::cssstyledeclaration::{CSSStyleDeclaration, CSSModificationAccess};
|
||||
use dom::document::{Document, DocumentHelpers};
|
||||
use dom::document::Document;
|
||||
use dom::domstringmap::DOMStringMap;
|
||||
use dom::element::{Element, ElementTypeId, ActivationElementHelpers, AttributeHandlers};
|
||||
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
||||
use dom::element::{Element, ElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::htmlinputelement::HTMLInputElement;
|
||||
use dom::htmlmediaelement::HTMLMediaElementTypeId;
|
||||
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::window::WindowHelpers;
|
||||
|
||||
use msg::constellation_msg::FocusType;
|
||||
use util::str::DOMString;
|
||||
|
@ -40,7 +38,6 @@ use std::intrinsics;
|
|||
use std::rc::Rc;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLElement {
|
||||
element: Element,
|
||||
style_decl: MutNullableHeap<JS<CSSStyleDeclaration>>,
|
||||
|
@ -80,20 +77,13 @@ impl HTMLElement {
|
|||
let element = HTMLElement::new_inherited(HTMLElementTypeId::HTMLElement, localName, prefix, document);
|
||||
Node::reflect_node(box element, document, HTMLElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
trait PrivateHTMLElementHelpers {
|
||||
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 {
|
||||
fn is_body_or_frameset(&self) -> bool {
|
||||
let eventtarget = EventTargetCast::from_ref(self);
|
||||
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 node = NodeCast::from_ref(self);
|
||||
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
|
||||
fn Style(self) -> Root<CSSStyleDeclaration> {
|
||||
fn Style(&self) -> Root<CSSStyleDeclaration> {
|
||||
self.style_decl.or_init(|| {
|
||||
let global = window_from_node(self);
|
||||
CSSStyleDeclaration::new(global.r(), ElementCast::from_ref(self), None, CSSModificationAccess::ReadWrite)
|
||||
})
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#attr-title
|
||||
make_getter!(Title);
|
||||
// https://html.spec.whatwg.org/multipage/#attr-title
|
||||
make_setter!(SetTitle, "title");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#attr-lang
|
||||
make_getter!(Lang);
|
||||
// https://html.spec.whatwg.org/multipage/#attr-lang
|
||||
make_setter!(SetLang, "lang");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hidden
|
||||
make_bool_getter!(Hidden);
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hidden
|
||||
make_bool_setter!(SetHidden, "hidden");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
|
||||
global_event_handlers!(NoOnload);
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
// 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() {
|
||||
let win = window_from_node(self);
|
||||
win.r().GetOnload()
|
||||
|
@ -169,7 +165,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// 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() {
|
||||
let win = window_from_node(self);
|
||||
win.r().SetOnload(listener)
|
||||
|
@ -180,7 +176,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-click
|
||||
fn Click(self) {
|
||||
fn Click(&self) {
|
||||
let maybe_input: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(self);
|
||||
if let Some(i) = maybe_input {
|
||||
if i.Disabled() {
|
||||
|
@ -193,7 +189,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// 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.
|
||||
// https://html.spec.whatwg.org/multipage/#focusing-steps
|
||||
let element = ElementCast::from_ref(self);
|
||||
|
@ -205,7 +201,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-blur
|
||||
fn Blur(self) {
|
||||
fn Blur(&self) {
|
||||
// TODO: Run the unfocusing steps.
|
||||
let node = NodeCast::from_ref(self);
|
||||
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
|
||||
fn GetOffsetParent(self) -> Option<Root<Element>> {
|
||||
fn GetOffsetParent(&self) -> Option<Root<Element>> {
|
||||
if self.is_htmlbodyelement() || self.is_htmlhtmlelement() {
|
||||
return None;
|
||||
}
|
||||
|
@ -232,7 +228,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn OffsetTop(self) -> i32 {
|
||||
fn OffsetTop(&self) -> i32 {
|
||||
if self.is_htmlbodyelement() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -245,7 +241,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn OffsetLeft(self) -> i32 {
|
||||
fn OffsetLeft(&self) -> i32 {
|
||||
if self.is_htmlbodyelement() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -258,7 +254,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
}
|
||||
|
||||
// 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 window = window_from_node(self);
|
||||
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
|
||||
fn OffsetHeight(self) -> i32 {
|
||||
fn OffsetHeight(&self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
let window = window_from_node(self);
|
||||
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-*
|
||||
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 {
|
||||
let mut attr_name = "data-".to_owned();
|
||||
|
@ -296,8 +287,8 @@ fn to_snake_case(name: DOMString) -> DOMString {
|
|||
attr_name
|
||||
}
|
||||
|
||||
impl<'a> HTMLElementCustomAttributeHelpers for &'a HTMLElement {
|
||||
fn set_custom_attr(self, name: DOMString, value: DOMString) -> ErrorResult {
|
||||
impl HTMLElement {
|
||||
pub fn set_custom_attr(&self, name: DOMString, value: DOMString) -> ErrorResult {
|
||||
if name.chars()
|
||||
.skip_while(|&ch| ch != '\u{2d}')
|
||||
.nth(1).map_or(false, |ch| ch >= 'a' && ch <= 'z') {
|
||||
|
@ -307,7 +298,7 @@ impl<'a> HTMLElementCustomAttributeHelpers for &'a HTMLElement {
|
|||
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 local_name = Atom::from_slice(&to_snake_case(local_name));
|
||||
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 local_name = Atom::from_slice(&to_snake_case(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> {
|
||||
let element: &&Element = ElementCast::from_borrowed_ref(self);
|
||||
let element: &Element = ElementCast::from_ref(self);
|
||||
Some(element as &VirtualMethods)
|
||||
}
|
||||
|
||||
|
@ -348,11 +339,11 @@ impl<'a> VirtualMethods for &'a HTMLElement {
|
|||
|
||||
let name = attr.local_name();
|
||||
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(),
|
||||
window.r().get_url(),
|
||||
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,
|
||||
&name[2..],
|
||||
(**attr.value()).to_owned());
|
||||
|
|
|
@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
|
|||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct HTMLEmbedElement {
|
||||
htmlelement: HTMLElement
|
||||
}
|
||||
|
@ -41,4 +40,3 @@ impl HTMLEmbedElement {
|
|||
Node::reflect_node(box element, document, HTMLEmbedElementBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue