aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/canvas/webgl_paint_task.rs21
-rw-r--r--components/canvas_traits/lib.rs4
-rw-r--r--components/compositing/lib.rs4
-rw-r--r--components/devtools/actor.rs71
-rw-r--r--components/devtools/actors/console.rs2
-rw-r--r--components/devtools/actors/timeline.rs77
-rw-r--r--components/devtools/lib.rs5
-rw-r--r--components/devtools_traits/lib.rs39
-rw-r--r--components/gfx/font.rs8
-rw-r--r--components/gfx/font_context.rs6
-rw-r--r--components/gfx/lib.rs18
-rw-r--r--components/gfx/paint_context.rs339
-rw-r--r--components/gfx/platform/freetype/font_list.rs4
-rw-r--r--components/gfx/platform/macos/font.rs5
-rw-r--r--components/gfx/platform/mod.rs8
-rw-r--r--components/gfx/text/glyph.rs177
-rw-r--r--components/gfx/text/shaping/harfbuzz.rs4
-rw-r--r--components/layout/block.rs54
-rw-r--r--components/layout/data.rs2
-rw-r--r--components/layout/display_list_builder.rs24
-rw-r--r--components/layout/flex.rs4
-rw-r--r--components/layout/flow.rs90
-rw-r--r--components/layout/fragment.rs15
-rw-r--r--components/layout/incremental.rs4
-rw-r--r--components/layout/inline.rs28
-rw-r--r--components/layout/list_item.rs4
-rw-r--r--components/layout/table.rs16
-rw-r--r--components/layout/table_row.rs12
-rw-r--r--components/layout/table_wrapper.rs75
-rw-r--r--components/layout/traversal.rs4
-rw-r--r--components/msg/lib.rs4
-rw-r--r--components/net/http_loader.rs719
-rw-r--r--components/net/mime_classifier.rs21
-rw-r--r--components/net/resource_task.rs48
-rw-r--r--components/net_traits/lib.rs1
-rw-r--r--components/plugins/utils.rs4
-rw-r--r--components/profile/lib.rs4
-rw-r--r--components/profile/mem.rs30
-rw-r--r--components/script/Cargo.toml4
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py105
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py7
-rw-r--r--components/script/dom/bindings/codegen/GlobalGen.py34
-rw-r--r--components/script/dom/bindings/codegen/pythonpath.py61
-rw-r--r--components/script/dom/bindings/mod.rs10
-rw-r--r--components/script/dom/bindings/num.rs2
-rw-r--r--components/script/dom/bindings/trace.rs14
-rw-r--r--components/script/dom/cssstyledeclaration.rs1
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs1
-rw-r--r--components/script/dom/document.rs3
-rw-r--r--components/script/dom/element.rs4
-rw-r--r--components/script/dom/filereader.rs11
-rw-r--r--components/script/dom/formdata.rs19
-rw-r--r--components/script/dom/htmlappletelement.rs2
-rw-r--r--components/script/dom/htmlbodyelement.rs2
-rw-r--r--components/script/dom/htmlbuttonelement.rs9
-rw-r--r--components/script/dom/htmlcollection.rs2
-rw-r--r--components/script/dom/htmlelement.rs6
-rw-r--r--components/script/dom/htmlfontelement.rs3
-rw-r--r--components/script/dom/htmlformelement.rs2
-rw-r--r--components/script/dom/htmliframeelement.rs6
-rw-r--r--components/script/dom/htmlimageelement.rs24
-rw-r--r--components/script/dom/htmlinputelement.rs2
-rw-r--r--components/script/dom/htmllinkelement.rs15
-rw-r--r--components/script/dom/htmlscriptelement.rs3
-rw-r--r--components/script/dom/htmltablecellelement.rs2
-rw-r--r--components/script/dom/htmltextareaelement.rs4
-rw-r--r--components/script/dom/location.rs77
-rw-r--r--components/script/dom/node.rs3
-rw-r--r--components/script/dom/nodelist.rs5
-rw-r--r--components/script/dom/progressevent.rs6
-rw-r--r--components/script/dom/testbinding.rs4
-rw-r--r--components/script/dom/testbindingproxy.rs14
-rw-r--r--components/script/dom/url.rs105
-rw-r--r--components/script/dom/urlhelper.rs59
-rw-r--r--components/script/dom/webglshader.rs57
-rw-r--r--components/script/dom/webidls/CSSStyleDeclaration.webidl104
-rw-r--r--components/script/dom/webidls/TestBinding.webidl2
-rw-r--r--components/script/dom/webidls/URLUtils.webidl30
-rw-r--r--components/script/dom/webidls/Worker.webidl2
-rw-r--r--components/script/dom/websocket.rs7
-rw-r--r--components/script/dom/window.rs20
-rw-r--r--components/script/dom/worker.rs4
-rw-r--r--components/script/dom/xmlhttprequest.rs3
-rw-r--r--components/script/dom/xmlhttprequesteventtarget.rs13
-rw-r--r--components/script/lib.rs7
-rw-r--r--components/script/makefile.cargo23
-rw-r--r--components/script/script_task.rs15
-rw-r--r--components/script/textinput.rs4
-rw-r--r--components/script/timers.rs4
-rw-r--r--components/servo/Cargo.lock21
-rw-r--r--components/servo/Cargo.toml27
-rw-r--r--components/servo/lib.rs77
-rw-r--r--components/servo/main.rs28
-rw-r--r--components/style/properties.mako.rs3
-rw-r--r--components/style/values.rs11
-rw-r--r--components/util/opts.rs15
-rw-r--r--ports/cef/Cargo.lock13
-rw-r--r--ports/glutin/lib.rs6
-rw-r--r--ports/glutin/window.rs36
-rw-r--r--ports/gonk/Cargo.lock11
-rw-r--r--python/servo/build_commands.py3
-rw-r--r--python/tidy.py87
-rw-r--r--tests/ref/absolute_table.html7
-rw-r--r--tests/ref/absolute_table_ref.html7
-rw-r--r--tests/ref/basic.list3
-rw-r--r--tests/ref/border_radius_asymmetric_sizes_a.html71
-rw-r--r--tests/ref/border_radius_asymmetric_sizes_ref.html217
-rw-r--r--tests/ref/position_relative_vertical_percentage_overflow_a.html25
-rw-r--r--tests/ref/position_relative_vertical_percentage_overflow_ref.html17
-rw-r--r--tests/ref/webgl-context/tex_image_2d_simple.html2
-rw-r--r--tests/unit/net/Cargo.toml1
-rw-r--r--tests/unit/net/http_loader.rs666
-rw-r--r--tests/unit/net/lib.rs3
-rw-r--r--tests/unit/net/mime_classifier.rs7
-rw-r--r--tests/unit/net/parsable_mime/text/xml/rdf_rss.xml7
-rw-r--r--tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_1.xml7
-rw-r--r--tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_2.xml3
-rw-r--r--tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_3.xml6
-rw-r--r--tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_4.xml7
-rw-r--r--tests/unit/script/textinput.rs62
-rw-r--r--tests/wpt/include.ini12
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-069.htm.ini3
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-177.htm.ini3
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-193.htm.ini3
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-176.htm.ini3
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-192.htm.ini3
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/absolute-replaced-width-015.htm.ini3
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.html.ini3
-rw-r--r--tests/wpt/metadata/url/interfaces.html.ini30
-rw-r--r--tests/wpt/metadata/workers/constructors/SharedWorker/__dir__.ini1
-rw-r--r--tests/wpt/metadata/workers/semantics/navigation/001.html.ini3
-rw-r--r--tests/wpt/metadata/workers/semantics/navigation/002.html.ini5
-rw-r--r--tests/wpt/metadata/workers/semantics/reporting-errors/__dir__.ini1
-rw-r--r--tests/wpt/metadata/workers/semantics/structured-clone/__dir__.ini1
134 files changed, 3160 insertions, 1251 deletions
diff --git a/components/canvas/webgl_paint_task.rs b/components/canvas/webgl_paint_task.rs
index b434f468711..aad45c916aa 100644
--- a/components/canvas/webgl_paint_task.rs
+++ b/components/canvas/webgl_paint_task.rs
@@ -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,
diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs
index 068eada3d9d..6f2924d2171 100644
--- a/components/canvas_traits/lib.rs
+++ b/components/canvas_traits/lib.rs
@@ -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),
diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs
index 95eba39c8e7..92a633674b4 100644
--- a/components/compositing/lib.rs
+++ b/components/compositing/lib.rs
@@ -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};
diff --git a/components/devtools/actor.rs b/components/devtools/actor.rs
index c640822d732..ca09e831dbb 100644
--- a/components/devtools/actor.rs
+++ b/components/devtools/actor.rs
@@ -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>();
-
- // 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);
+trait ActorAsAny {
+ fn actor_as_any(&self) -> &Any;
+ fn actor_as_any_mut(&mut self) -> &mut Any;
+}
- // 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
diff --git a/components/devtools/actors/console.rs b/components/devtools/actors/console.rs
index 7c859369274..30c0b98d77a 100644
--- a/components/devtools/actors/console.rs
+++ b/components/devtools/actors/console.rs
@@ -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;
diff --git a/components/devtools/actors/timeline.rs b/components/devtools/actors/timeline.rs
index 17327b1043e..b38b85a97b5 100644
--- a/components/devtools/actors/timeline.rs
+++ b/components/devtools/actors/timeline.rs
@@ -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,
}
}
diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs
index 07a3889d699..4be05c919d1 100644
--- a/components/devtools/lib.rs
+++ b/components/devtools/lib.rs
@@ -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;
diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs
index 8df97634fad..c8889fcd5fb 100644
--- a/components/devtools_traits/lib.rs
+++ b/components/devtools_traits/lib.rs
@@ -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,
}
}
}
diff --git a/components/gfx/font.rs b/components/gfx/font.rs
index fd17fa4e467..ba11c2a63cc 100644
--- a/components/gfx/font.rs
+++ b/components/gfx/font.rs
@@ -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,
}
}
diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs
index 18ee5e9ff42..640b2b8250c 100644
--- a/components/gfx/font_context.rs
+++ b/components/gfx/font_context.rs
@@ -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())
diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs
index 6ffbe36fb5b..db73b9b200d 100644
--- a/components/gfx/lib.rs
+++ b/components/gfx/lib.rs
@@ -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
diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs
index a96d413cafc..2c38e0e6fea 100644
--- a/components/gfx/paint_context.rs
+++ b/components/gfx/paint_context.rs
@@ -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.);
-
- path_builder.arc(origin, radius.top_right, rad_T, rad_TR, false);
- path_builder.arc(origin, distance_to_elbow, rad_TR, rad_T, true);
+ 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_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.);
-
- path_builder.arc(origin, distance_to_elbow, rad_L, rad_BL, true);
- path_builder.arc(origin, radius.bottom_left, rad_BL, rad_L, false);
+ (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()
+ };
+
+ 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.);
-
- path_builder.arc(origin, radius.bottom_right, rad_R, rad_BR, false);
- path_builder.arc(origin, distance_to_elbow, rad_BR, rad_R, true);
+ (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_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.);
-
- path_builder.arc(origin, distance_to_elbow, rad_B, rad_BR, true);
- path_builder.arc(origin, radius.bottom_right, rad_BR, rad_B, false);
+ 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()
+ };
+
+ 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.);
-
- path_builder.arc(origin, radius.bottom_left, rad_B, rad_BL, false);
- path_builder.arc(origin, distance_to_elbow, rad_BL, rad_B, true);
+ 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_L - angle, false);
+ if distance_to_elbow_BL != 0. {
+ path_builder.arc(origin, distance_to_elbow_BL, rad_L - angle, rad_B, true);
+ }
}
}
}
@@ -960,14 +1176,13 @@ impl<'a> PaintContext<'a> {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let font = self.font_context.get_paint_font_from_template(
&text.text_run.font_template, text.text_run.actual_pt_size);
- font
- .borrow()
- .draw_text(&temporary_draw_target.draw_target,
- &*text.text_run,
- &text.range,
- baseline_origin,
- text.text_color,
- opts::get().enable_text_antialiasing);
+ font.borrow()
+ .draw_text(&temporary_draw_target.draw_target,
+ &*text.text_run,
+ &text.range,
+ baseline_origin,
+ text.text_color,
+ opts::get().enable_text_antialiasing);
}
// Blur, if necessary.
@@ -1029,8 +1244,9 @@ impl<'a> PaintContext<'a> {
// Calculate the transform matrix.
let old_transform = self.draw_target.get_transform();
- let inflated_size = Rect::new(Point2D::new(0.0, 0.0), Size2D::new(size.width as AzFloat,
- size.height as AzFloat));
+ let inflated_size = Rect::new(Point2D::new(0.0, 0.0),
+ Size2D::new(size.width as AzFloat,
+ size.height as AzFloat));
let temporary_draw_target_bounds = old_transform.transform_rect(&inflated_size);
matrix = Matrix2D::identity().translate(
-temporary_draw_target_bounds.origin.x as AzFloat,
@@ -1060,7 +1276,8 @@ impl<'a> PaintContext<'a> {
self.draw_target.set_transform(&Matrix2D::identity());
let rect = Rect::new(Point2D::new(0.0, 0.0), self.draw_target.get_size().to_azure_size());
- let rect_temporary = Rect::new(Point2D::new(0.0, 0.0), temporary_draw_target.get_size().to_azure_size());
+ let rect_temporary = Rect::new(Point2D::new(0.0, 0.0),
+ temporary_draw_target.get_size().to_azure_size());
// Create the Azure filter pipeline.
let mut accum_blur = Au(0);
@@ -1081,7 +1298,10 @@ impl<'a> PaintContext<'a> {
self.pop_clip_if_applicable();
debug!("######### use expanded Rect.");
- self.draw_target.draw_filter(&filter_node, &rect_temporary, &rect_temporary.origin, draw_options);
+ self.draw_target.draw_filter(&filter_node,
+ &rect_temporary,
+ &rect_temporary.origin,
+ draw_options);
self.push_clip_if_applicable();
} else {
debug!("######### use regular Rect.");
@@ -1132,9 +1352,10 @@ impl<'a> PaintContext<'a> {
}
// Draw the shadow, and blur if we need to.
- temporary_draw_target.draw_target.fill(&path,
- Pattern::Color(ColorPattern::new(color)).to_pattern_ref(),
- &DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None));
+ temporary_draw_target.draw_target.fill(
+ &path,
+ Pattern::Color(ColorPattern::new(color)).to_pattern_ref(),
+ &DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None));
self.blur_if_necessary(temporary_draw_target, blur_radius);
// Undo the draw target's clip if we need to, and push back the stacking context clip.
diff --git a/components/gfx/platform/freetype/font_list.rs b/components/gfx/platform/freetype/font_list.rs
index f3557d7dd2f..9e0a5177312 100644
--- a/components/gfx/platform/freetype/font_list.rs
+++ b/components/gfx/platform/freetype/font_list.rs
@@ -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())
}
diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs
index b96f217e0c9..eb33e326230 100644
--- a/components/gfx/platform/macos/font.rs
+++ b/components/gfx/platform/macos/font.rs
@@ -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 }
diff --git a/components/gfx/platform/mod.rs b/components/gfx/platform/mod.rs
index f3bc3f6ec08..085da7cc932 100644
--- a/components/gfx/platform/mod.rs
+++ b/components/gfx/platform/mod.rs
@@ -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;
diff --git a/components/gfx/text/glyph.rs b/components/gfx/text/glyph.rs
index 29918e5d2d9..d27128014b5 100644
--- a/components/gfx/text/glyph.rs
+++ b/components/gfx/text/glyph.rs
@@ -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() {
diff --git a/components/gfx/text/shaping/harfbuzz.rs b/components/gfx/text/shaping/harfbuzz.rs
index 462d5bf485c..426068a4106 100644
--- a/components/gfx/text/shaping/harfbuzz.rs
+++ b/components/gfx/text/shaping/harfbuzz.rs
@@ -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
}
diff --git a/components/layout/block.rs b/components/layout/block.rs
index d697cad97a9..3926384379a 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -36,10 +36,10 @@ use flow::{CLEARS_LEFT, CLEARS_RIGHT};
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC};
use flow::{IS_ABSOLUTELY_POSITIONED};
-use flow::{ImmutableFlowUtils, MutableFlowUtils, OpaqueFlow, PreorderFlowTraversal};
+use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
-use flow::{PostorderFlowTraversal, mut_base};
-use flow::{self, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
+use flow::{PostorderFlowTraversal, PreorderFlowTraversal, mut_base};
+use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, ForceNonfloatedFlag, FlowClass, Flow};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER};
use fragment::{SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
@@ -485,7 +485,7 @@ impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
}
}
- flow.store_overflow(self.layout_context);
+ flow.early_store_overflow(self.layout_context);
}
}
@@ -561,7 +561,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,
}
}
@@ -959,6 +959,19 @@ impl BlockFlow {
//
// FIXME(pcwalton): This looks not idempotent. Is it?
self.fragment.border_box.size.block = block_size;
+ }
+
+ // Write in the size of the relative containing block for children. (This information
+ // is also needed to handle RTL.)
+ for kid in self.base.child_iter() {
+ flow::mut_base(kid).early_absolute_position_info = EarlyAbsolutePositionInfo {
+ relative_containing_block_size: self.fragment.content_box().size,
+ relative_containing_block_mode: self.fragment.style().writing_mode,
+ };
+ kid.late_store_overflow(layout_context)
+ }
+
+ if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
return
}
@@ -1730,7 +1743,7 @@ impl Flow for BlockFlow {
self.base.thread_id = parent_thread_id;
if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
self.assign_block_size(layout_context);
- self.store_overflow(layout_context);
+ (self as &mut Flow).early_store_overflow(layout_context);
// Don't remove the restyle damage; `assign_block_size` decides whether that is
// appropriate (which in the case of e.g. absolutely-positioned flows, it is not).
}
@@ -1775,7 +1788,7 @@ impl Flow for BlockFlow {
fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
if (self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
- self.base.absolute_position_info.layers_needed_for_positioned_flows) ||
+ self.base.late_absolute_position_info.layers_needed_for_positioned_flows) ||
self.base.flags.contains(NEEDS_LAYER) {
self.fragment.flags.insert(HAS_LAYER)
}
@@ -1816,7 +1829,7 @@ impl Flow for BlockFlow {
// Absolute position of the containing block + position of absolute
// flow w.r.t. the containing block.
self.base
- .absolute_position_info
+ .late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block + position_start
};
@@ -1842,13 +1855,13 @@ impl Flow for BlockFlow {
// other hand, is only established if we are positioned.
let relative_offset =
self.fragment.relative_position(&self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size);
if self.contains_positioned_fragments() {
let border_box_origin = (self.fragment.border_box -
self.fragment.style.logical_border_width()).start;
self.base
- .absolute_position_info
+ .late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block =
self.base.stacking_relative_position +
(border_box_origin + relative_offset).to_physical(self.base.writing_mode,
@@ -1875,14 +1888,12 @@ impl Flow for BlockFlow {
}
} else {
self.base
- .absolute_position_info
+ .late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block
};
- let absolute_position_info_for_children = AbsolutePositionInfo {
+ let late_absolute_position_info_for_children = LateAbsolutePositionInfo {
stacking_relative_position_of_absolute_containing_block:
stacking_relative_position_of_absolute_containing_block_for_children,
- relative_containing_block_size: self.fragment.content_box().size,
- relative_containing_block_mode: self.base.writing_mode,
layers_needed_for_positioned_flows: self.base
.flags
.contains(LAYERS_NEEDED_FOR_DESCENDANTS),
@@ -1934,10 +1945,10 @@ impl Flow for BlockFlow {
self.fragment
.stacking_relative_border_box(&self.base.stacking_relative_position,
&self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size,
self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Own);
let clip = self.fragment.clipping_region_for_children(
@@ -1985,7 +1996,8 @@ impl Flow for BlockFlow {
}
}
- flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
+ flow::mut_base(kid).late_absolute_position_info =
+ late_absolute_position_info_for_children;
flow::mut_base(kid).clip = clip.clone();
flow::mut_base(kid).stacking_relative_position_of_display_port =
stacking_relative_position_of_display_port_for_children;
@@ -2056,7 +2068,9 @@ impl Flow for BlockFlow {
}
fn compute_overflow(&self) -> Rect<Au> {
- self.fragment.compute_overflow()
+ self.fragment.compute_overflow(&self.base
+ .early_absolute_position_info
+ .relative_containing_block_size)
}
fn iterate_through_fragment_border_boxes(&self,
@@ -2072,10 +2086,10 @@ impl Flow for BlockFlow {
&self.fragment
.stacking_relative_border_box(&self.base.stacking_relative_position,
&self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size,
self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Own)
.translate(stacking_context_position));
diff --git a/components/layout/data.rs b/components/layout/data.rs
index 4b551e2fd9e..097852096fa 100644
--- a/components/layout/data.rs
+++ b/components/layout/data.rs
@@ -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
}
}
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 0485d549c4a..19c466ee528 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -1152,9 +1152,9 @@ impl FragmentDisplayListBuilding for Fragment {
StackingContextCreationMode::Normal |
StackingContextCreationMode::OuterScrollWrapper => {
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
- &base_flow.absolute_position_info
+ &base_flow.early_absolute_position_info
.relative_containing_block_size,
- base_flow.absolute_position_info
+ base_flow.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Parent)
}
@@ -1533,8 +1533,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
.build_display_list(display_list,
layout_context,
&self.base.stacking_relative_position,
- &self.base.absolute_position_info.relative_containing_block_size,
- self.base.absolute_position_info.relative_containing_block_mode,
+ &self.base
+ .early_absolute_position_info
+ .relative_containing_block_size,
+ self.base
+ .early_absolute_position_info
+ .relative_containing_block_mode,
border_painting_mode,
background_border_level,
&clip,
@@ -1616,8 +1620,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&mut outer_display_list_for_overflow_scroll,
layout_context,
&self.base.stacking_relative_position,
- &self.base.absolute_position_info.relative_containing_block_size,
- self.base.absolute_position_info.relative_containing_block_mode,
+ &self.base.early_absolute_position_info.relative_containing_block_size,
+ self.base.early_absolute_position_info.relative_containing_block_mode,
border_painting_mode,
BackgroundAndBorderLevel::RootOfStackingContext,
&clip,
@@ -1775,10 +1779,10 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
layout_context,
&self.base.stacking_relative_position,
&self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size,
self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_mode,
BorderPaintingMode::Separate,
BackgroundAndBorderLevel::Content,
@@ -1857,11 +1861,11 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
&self.block_flow.base.stacking_relative_position,
&self.block_flow
.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size,
self.block_flow
.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_mode,
BorderPaintingMode::Separate,
BackgroundAndBorderLevel::Content,
diff --git a/components/layout/flex.rs b/components/layout/flex.rs
index 3c34aeaf728..88fe929a9d3 100644
--- a/components/layout/flex.rs
+++ b/components/layout/flex.rs
@@ -312,6 +312,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());
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 6d319bdd991..4e2da89f513 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -222,7 +222,11 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
if impacted {
mut_base(self).thread_id = parent_thread_id;
self.assign_block_size(layout_context);
- self.store_overflow(layout_context);
+ // FIXME(pcwalton): Should use `early_store_overflow()` here but that fails due to a
+ // compiler bug (`Self` does not have a constant size).
+ if !self.contains_relatively_positioned_fragments() {
+ self.store_overflow(layout_context)
+ }
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
impacted
@@ -246,7 +250,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
match self.class() {
FlowClass::Block |
FlowClass::TableCaption |
- FlowClass::TableCell if !base(self).children.is_empty() => {
+ FlowClass::TableCell => {
// FIXME(#2795): Get the real container size.
let container_size = Size2D::zero();
for kid in mut_base(self).children.iter_mut() {
@@ -310,13 +314,6 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
// different behaviour for different types of Flow, so they can't go into
// the Immutable / Mutable Flow Utils traits without additional casts.
- /// Return true if store overflow is delayed for this flow.
- ///
- /// Currently happens only for absolutely positioned flows.
- fn is_store_overflow_delayed(&mut self) -> bool {
- false
- }
-
fn is_root(&self) -> bool {
false
}
@@ -459,6 +456,11 @@ pub trait ImmutableFlowUtils {
/// Returns true if this flow is an inline flow.
fn is_inline_flow(self) -> bool;
+ /// Returns true if this flow can have its overflow area calculated early (during its
+ /// block-size assignment) or false if it must have its overflow area calculated late (during
+ /// its parent's block-size assignment).
+ fn can_calculate_overflow_area_early(self) -> bool;
+
/// Dumps the flow tree for debugging.
fn dump(self);
@@ -495,6 +497,12 @@ pub trait MutableFlowUtils {
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
/// calling them individually, since there is no reason not to perform both operations.
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
+
+ /// Calls `store_overflow()` if the overflow can be calculated early.
+ fn early_store_overflow(self, layout_context: &LayoutContext);
+
+ /// Calls `store_overflow()` if the overflow cannot be calculated early.
+ fn late_store_overflow(self, layout_context: &LayoutContext);
}
pub trait MutableOwnedFlowUtils {
@@ -780,15 +788,30 @@ impl<'a> Iterator for AbsoluteDescendantIter<'a> {
pub type AbsoluteDescendantOffsetIter<'a> = Zip<AbsoluteDescendantIter<'a>, IterMut<'a, Au>>;
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
-/// confused with absolutely-positioned flows).
-#[derive(RustcEncodable, Copy, Clone)]
-pub struct AbsolutePositionInfo {
+/// confused with absolutely-positioned flows) that is computed during block-size assignment.
+pub struct EarlyAbsolutePositionInfo {
/// The size of the containing block for relatively-positioned descendants.
pub relative_containing_block_size: LogicalSize<Au>,
/// The writing mode for `relative_containing_block_size`.
pub relative_containing_block_mode: WritingMode,
+}
+
+impl EarlyAbsolutePositionInfo {
+ pub fn new(writing_mode: WritingMode) -> EarlyAbsolutePositionInfo {
+ // FIXME(pcwalton): The initial relative containing block-size should be equal to the size
+ // of the root layer.
+ EarlyAbsolutePositionInfo {
+ relative_containing_block_size: LogicalSize::zero(writing_mode),
+ relative_containing_block_mode: writing_mode,
+ }
+ }
+}
+/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
+/// confused with absolutely-positioned flows) that is computed during final position assignment.
+#[derive(RustcEncodable, Copy, Clone)]
+pub struct LateAbsolutePositionInfo {
/// The position of the absolute containing block relative to the nearest ancestor stacking
/// context. If the absolute containing block establishes the stacking context for this flow,
/// and this flow is not itself absolutely-positioned, then this is (0, 0).
@@ -800,13 +823,9 @@ pub struct AbsolutePositionInfo {
pub layers_needed_for_positioned_flows: bool,
}
-impl AbsolutePositionInfo {
- pub fn new(writing_mode: WritingMode) -> AbsolutePositionInfo {
- // FIXME(pcwalton): The initial relative containing block-size should be equal to the size
- // of the root layer.
- AbsolutePositionInfo {
- relative_containing_block_size: LogicalSize::zero(writing_mode),
- relative_containing_block_mode: writing_mode,
+impl LateAbsolutePositionInfo {
+ pub fn new() -> LateAbsolutePositionInfo {
+ LateAbsolutePositionInfo {
stacking_relative_position_of_absolute_containing_block: Point2D::zero(),
layers_needed_for_positioned_flows: false,
}
@@ -875,8 +894,13 @@ pub struct BaseFlow {
pub absolute_cb: ContainingBlockLink,
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
- /// confused with absolutely-positioned flows).
- pub absolute_position_info: AbsolutePositionInfo,
+ /// confused with absolutely-positioned flows) that is computed during block-size assignment.
+ pub early_absolute_position_info: EarlyAbsolutePositionInfo,
+
+ /// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
+ /// confused with absolutely-positioned flows) that is computed during final position
+ /// assignment.
+ pub late_absolute_position_info: LateAbsolutePositionInfo,
/// The clipping region for this flow and its descendants, in layer coordinates.
pub clip: ClippingRegion,
@@ -1038,7 +1062,8 @@ impl BaseFlow {
block_container_explicit_block_size: None,
absolute_cb: ContainingBlockLink::new(),
display_list_building_result: DisplayListBuildingResult::None,
- absolute_position_info: AbsolutePositionInfo::new(writing_mode),
+ early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
+ late_absolute_position_info: LateAbsolutePositionInfo::new(),
clip: ClippingRegion::max(),
stacking_relative_position_of_display_port: Rect::zero(),
flags: flags,
@@ -1276,6 +1301,13 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
}
}
+ /// Returns true if this flow can have its overflow area calculated early (during its
+ /// block-size assignment) or false if it must have its overflow area calculated late (during
+ /// its parent's block-size assignment).
+ fn can_calculate_overflow_area_early(self) -> bool {
+ !self.contains_relatively_positioned_fragments()
+ }
+
/// Dumps the flow tree for debugging.
fn dump(self) {
self.dump_with_level(0)
@@ -1354,6 +1386,20 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
traversal.process(*self)
}
+
+ /// Calls `store_overflow()` if the overflow can be calculated early.
+ fn early_store_overflow(self, layout_context: &LayoutContext) {
+ if self.can_calculate_overflow_area_early() {
+ self.store_overflow(layout_context)
+ }
+ }
+
+ /// Calls `store_overflow()` if the overflow cannot be calculated early.
+ fn late_store_overflow(self, layout_context: &LayoutContext) {
+ if !self.can_calculate_overflow_area_early() {
+ self.store_overflow(layout_context)
+ }
+ }
}
impl MutableOwnedFlowUtils for FlowRef {
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 02af5569d84..3b9596d27b9 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -2049,7 +2049,7 @@ impl Fragment {
}
/// Computes the overflow rect of this fragment relative to the start of the flow.
- pub fn compute_overflow(&self) -> Rect<Au> {
+ pub fn compute_overflow(&self, relative_containing_block_size: &LogicalSize<Au>) -> Rect<Au> {
// FIXME(pcwalton, #2795): Get the real container size.
let container_size = Size2D::zero();
let mut border_box = self.border_box.to_physical(self.style.writing_mode, container_size);
@@ -2058,10 +2058,9 @@ impl Fragment {
//
// FIXME(pcwalton): I'm not a fan of the way this makes us crawl though so many styles all
// the time. Can't we handle relative positioning by just adjusting `border_box`?
- let relative_position =
- self.relative_position(&LogicalSize::zero(self.style.writing_mode));
- border_box = border_box.translate_by_size(&relative_position.to_physical(
- self.style.writing_mode));
+ let relative_position = self.relative_position(relative_containing_block_size);
+ border_box =
+ border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode));
let mut overflow = border_box;
// Box shadows cause us to draw outside our border box.
@@ -2300,10 +2299,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,
}
}
diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs
index 623fa4685fe..14205b32cb5 100644
--- a/components/layout/incremental.rs
+++ b/components/layout/incremental.rs
@@ -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,
}
}
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 4b5a6b985c7..17d6af7ccbc 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -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
}
}
@@ -1645,10 +1645,10 @@ impl Flow for InlineFlow {
let stacking_relative_border_box =
fragment.stacking_relative_border_box(&self.base.stacking_relative_position,
&self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size,
self.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Parent);
let clip = fragment.clipping_region_for_children(&self.base.clip,
@@ -1661,13 +1661,14 @@ impl Flow for InlineFlow {
flow::mut_base(flow).clip = clip;
let block_flow = flow.as_mut_block();
- block_flow.base.absolute_position_info = self.base.absolute_position_info;
+ block_flow.base.late_absolute_position_info =
+ self.base.late_absolute_position_info;
let stacking_relative_position = self.base.stacking_relative_position;
if is_positioned {
let padding_box_origin = containing_block_positions.next().unwrap();
block_flow.base
- .absolute_position_info
+ .late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block =
stacking_relative_position + *padding_box_origin;
}
@@ -1681,7 +1682,8 @@ impl Flow for InlineFlow {
let flow = flow_ref::deref_mut(&mut info.flow_ref);
flow::mut_base(flow).clip = clip;
let block_flow = flow.as_mut_block();
- block_flow.base.absolute_position_info = self.base.absolute_position_info;
+ block_flow.base.late_absolute_position_info =
+ self.base.late_absolute_position_info;
block_flow.base.stacking_relative_position =
stacking_relative_border_box.origin;
@@ -1693,12 +1695,13 @@ impl Flow for InlineFlow {
flow::mut_base(flow).clip = clip;
let block_flow = flow.as_mut_block();
- block_flow.base.absolute_position_info = self.base.absolute_position_info;
+ block_flow.base.late_absolute_position_info =
+ self.base.late_absolute_position_info;
let stacking_relative_position = self.base.stacking_relative_position;
let padding_box_origin = containing_block_positions.next().unwrap();
block_flow.base
- .absolute_position_info
+ .late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block =
stacking_relative_position + *padding_box_origin;
@@ -1725,7 +1728,8 @@ impl Flow for InlineFlow {
fn compute_overflow(&self) -> Rect<Au> {
let mut overflow = ZERO_RECT;
for fragment in &self.fragments.fragments {
- overflow = overflow.union(&fragment.compute_overflow())
+ overflow = overflow.union(&fragment.compute_overflow(
+ &self.base.early_absolute_position_info.relative_containing_block_size))
}
overflow
}
@@ -1742,9 +1746,9 @@ impl Flow for InlineFlow {
let stacking_relative_position = &self.base.stacking_relative_position;
let relative_containing_block_size =
- &self.base.absolute_position_info.relative_containing_block_size;
+ &self.base.early_absolute_position_info.relative_containing_block_size;
let relative_containing_block_mode =
- self.base.absolute_position_info.relative_containing_block_mode;
+ self.base.early_absolute_position_info.relative_containing_block_mode;
iterator.process(fragment,
level,
&fragment.stacking_relative_border_box(stacking_relative_position,
diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs
index b0c3702f2c2..7ba0786f906 100644
--- a/components/layout/list_item.rs
+++ b/components/layout/list_item.rs
@@ -184,11 +184,11 @@ impl Flow for ListItemFlow {
.stacking_relative_position,
&self.block_flow
.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_size,
self.block_flow
.base
- .absolute_position_info
+ .early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Own)
.translate(stacking_context_position));
diff --git a/components/layout/table.rs b/components/layout/table.rs
index f5ef95f1989..54e3f090b59 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -10,8 +10,8 @@ use block::{ISizeConstraintInput, ISizeConstraintSolution};
use block::{self, BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
-use flow::{ImmutableFlowUtils, OpaqueFlow};
-use flow::{self, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
+use flow::{IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils, MutableFlowUtils, OpaqueFlow};
+use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS};
use fragment::{Fragment, FragmentBorderBoxIterator};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
@@ -761,7 +761,7 @@ pub trait TableLikeFlow {
impl TableLikeFlow for BlockFlow {
fn assign_block_size_for_table_like_flow<'a>(&mut self,
- _: &'a LayoutContext<'a>,
+ layout_context: &'a LayoutContext<'a>,
block_direction_spacing: Au) {
debug_assert!(self.fragment.style.get_inheritedtable().border_collapse ==
border_collapse::T::separate || block_direction_spacing == Au(0));
@@ -838,6 +838,16 @@ impl TableLikeFlow for BlockFlow {
self.fragment.border_box.size.block = current_block_offset;
self.fragment.border_box.start.b = Au(0);
self.base.position.size.block = current_block_offset;
+
+ // Write in the size of the relative containing block for children. (This information
+ // is also needed to handle RTL.)
+ for kid in self.base.child_iter() {
+ flow::mut_base(kid).early_absolute_position_info = EarlyAbsolutePositionInfo {
+ relative_containing_block_size: self.fragment.content_box().size,
+ relative_containing_block_mode: self.fragment.style().writing_mode,
+ };
+ kid.late_store_overflow(layout_context)
+ }
}
self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index e2b155bca78..4043363a23a 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -9,7 +9,7 @@
use block::{BlockFlow, ISizeAndMarginsComputer};
use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
-use flow::{self, FlowClass, Flow, ImmutableFlowUtils, OpaqueFlow};
+use flow::{self, EarlyAbsolutePositionInfo, FlowClass, Flow, ImmutableFlowUtils, OpaqueFlow};
use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator};
use layout_debug;
@@ -162,7 +162,15 @@ impl TableRowFlow {
}
// Assign the child's block size.
- child_table_cell.block_flow.base.position.size.block = block_size
+ child_table_cell.block_flow.base.position.size.block = block_size;
+
+ // Write in the size of the relative containing block for children. (This information
+ // is also needed to handle RTL.)
+ child_table_cell.block_flow.base.early_absolute_position_info =
+ EarlyAbsolutePositionInfo {
+ relative_containing_block_size: self.block_flow.fragment.content_box().size,
+ relative_containing_block_mode: self.block_flow.fragment.style().writing_mode,
+ };
}
}
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index c3312bceba9..ebf96020634 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -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);
+ }
+
+}
+
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs
index 7c4687a1b00..ed8ae6ab76a 100644
--- a/components/layout/traversal.rs
+++ b/components/layout/traversal.rs
@@ -7,7 +7,7 @@
use construct::FlowConstructor;
use context::LayoutContext;
use css::matching::{ApplicableDeclarations, MatchMethods, StyleSharingResult};
-use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
+use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow::{self, Flow};
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
use script::layout_interface::ReflowGoal;
@@ -368,7 +368,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
}
flow.assign_block_size(self.layout_context);
- flow.store_overflow(self.layout_context);
+ flow.early_store_overflow(self.layout_context);
}
#[inline]
diff --git a/components/msg/lib.rs b/components/msg/lib.rs
index 7c03b73d591..34a87cfd805 100644
--- a/components/msg/lib.rs
+++ b/components/msg/lib.rs
@@ -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;
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index bc47b6aa709..4c257513526 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -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 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 devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent};
use file_loader;
use flate2::read::{DeflateDecoder, GzDecoder};
+use hsts::secure_url;
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::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::{HttpConnector, HttpsConnector, Openssl};
+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 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)
+ }
+ }
+}
+
+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)));
+ }
+ }
}
}
-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>>) {
+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 => {
+ //
+ // 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();
+ let response = match load_data.data {
+ Some(ref data) if !is_redirected_request => {
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
- },
+
+ // 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))
+ }
_ => {
- match load_data.method {
- Method::Get | Method::Head => (),
- _ => req.headers_mut().set(ContentLength(0))
+ if load_data.method != Method::Get && load_data.method != Method::Head {
+ req.headers_mut().set(ContentLength(0))
}
- match req.start() {
- Ok(w) => w,
- Err(e) => {
- send_error(url, e.description().to_string(), start_chan);
- return;
- }
- }
- }
- };
- // Send an HttpRequest message to devtools with a unique request_id
- // TODO: Do this only if load_data has some pipeline_id, and send the pipeline_id in the message
- let request_id = uuid::Uuid::new_v4().to_simple_string();
- 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();
- }
+ send_request_to_devtools(
+ devtools_chan.clone(), request_id.clone(), url.clone(),
+ method.clone(), load_data.headers.clone(),
+ None
+ );
- let mut response = match writer.send() {
- Ok(r) => r,
- Err(e) => {
- send_error(url, e.description().to_string(), start_chan);
- return;
+ 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();
- }
-
- 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);
- }
- }
+ // TODO: Send this message even when the load fails?
+ send_response_to_devtools(
+ devtools_chan, request_id,
+ metadata.headers.clone(), metadata.status.clone()
+ );
- // We didn't get redirected.
- break;
+ return StreamedResponse::from_http_response(response, metadata)
}
}
diff --git a/components/net/mime_classifier.rs b/components/net/mime_classifier.rs
index 0ed472b3982..de1b445abf4 100644
--- a/components/net/mime_classifier.rs
+++ b/components/net/mime_classifier.rs
@@ -125,6 +125,10 @@ 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 {
+ if self.clone().nth(matches.len()).is_none() {
+ // there are less than matches.len() elements in self
+ return false
+ }
let result = self.clone().zip(matches).all(|(s, m)| *s == *m);
if result {
self.nth(matches.len());
@@ -381,9 +385,10 @@ where T: Iterator<Item=&'a u8> + Clone {
struct FeedsClassifier;
impl FeedsClassifier {
+ // Implements sniffing for mislabeled feeds (https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-feed)
fn classify_impl(&self, data: &[u8]) -> Option<(&'static str, &'static str)> {
- // can not be feed unless length is > 3
+ // Step 4: can not be feed unless length is > 3
if data.len() < 3 {
return None;
}
@@ -403,6 +408,7 @@ impl FeedsClassifier {
return None;
}
+ // Steps 5.2.1 to 5.2.4
match eats_until(&mut matcher, b"?", b"?>")
.chain(|| eats_until(&mut matcher, b"!--", b"-->"))
.chain(|| eats_until(&mut matcher, b"!", b">")) {
@@ -411,20 +417,23 @@ impl FeedsClassifier {
Match::Start => return None
}
+ // Step 5.2.5
if matcher.matches(b"rss") {
return Some(("application", "rss+xml"));
}
+ // Step 5.2.6
if matcher.matches(b"feed") {
return Some(("application", "atom+xml"));
}
- if matcher.matches(b"rdf: RDF") {
+ // Step 5.2.7
+ 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#")
+ 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/")) {
+ 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
diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs
index 62566f71c70..d232db51bff 100644
--- a/components/net/resource_task.rs
+++ b/components/net/resource_task.rs
@@ -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),
_ => {
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index e4a93f56673..3f9db2a7ebc 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -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
}
diff --git a/components/plugins/utils.rs b/components/plugins/utils.rs
index 79025c33f70..e26cc4bc7cd 100644
--- a/components/plugins/utils.rs
+++ b/components/plugins/utils.rs
@@ -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
diff --git a/components/profile/lib.rs b/components/profile/lib.rs
index 9bf2018f4be..635b9af083f 100644
--- a/components/profile/lib.rs
+++ b/components/profile/lib.rs
@@ -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;
diff --git a/components/profile/mem.rs b/components/profile/mem.rs
index dae86a535fd..8b1e7b1397d 100644
--- a/components/profile/mem.rs
+++ b/components/profile/mem.rs
@@ -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![]
}
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index e52594d8c15..aa8967a62ae 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -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" ]
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 63f9d010729..08370974cca 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -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",
@@ -4021,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("""\
@@ -4218,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());
@@ -4338,7 +4351,7 @@ if !expando.ptr.is_null() {
namedGetter = self.descriptor.operations['NamedGetter']
if namedGetter:
- getNamed = ("if (RUST_JSID_IS_STRING(id) != 0) {\n" +
+ getNamed = ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
"}\n")
else:
@@ -5506,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"
@@ -5539,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
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
index 4e740f83a16..1a88968619b 100644
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ b/components/script/dom/bindings/codegen/Configuration.py
@@ -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:
diff --git a/components/script/dom/bindings/codegen/GlobalGen.py b/components/script/dom/bindings/codegen/GlobalGen.py
index b3ed1e25b12..537883fae57 100644
--- a/components/script/dom/bindings/codegen/GlobalGen.py
+++ b/components/script/dom/bindings/codegen/GlobalGen.py
@@ -28,7 +28,7 @@ def generate_file(config, name, filename):
def main():
# Parse arguments.
from optparse import OptionParser
- usageString = "usage: %prog [options] webidldir [files]"
+ usageString = "usage: %prog [options] configFile outputdir webidldir [files]"
o = OptionParser(usage=usageString)
o.add_option("--cachedir", dest='cachedir', default=None,
help="Directory in which to cache lex/parse tables.")
@@ -40,8 +40,9 @@ def main():
o.error(usageString)
configFile = args[0]
- baseDir = args[1]
- fileList = args[2:]
+ outputdir = args[1]
+ baseDir = args[2]
+ fileList = args[3:]
# Parse the WebIDL.
parser = WebIDL.Parser(options.cachedir)
@@ -59,22 +60,17 @@ def main():
# Load the configuration.
config = Configuration(configFile, parserResults)
- # Generate the prototype list.
- generate_file(config, 'PrototypeList', 'PrototypeList.rs')
-
- # Generate the common code.
- generate_file(config, 'RegisterBindings', 'RegisterBindings.rs')
-
- # Generate the type list.
- generate_file(config, 'InterfaceTypes', 'InterfaceTypes.rs')
-
- # Generate the type list.
- generate_file(config, 'InheritTypes', 'InheritTypes.rs')
-
- # Generate the module declarations.
- generate_file(config, 'Bindings', 'Bindings/mod.rs')
-
- generate_file(config, 'UnionTypes', 'UnionTypes.rs')
+ to_generate = [
+ ('PrototypeList', 'PrototypeList.rs'),
+ ('RegisterBindings', 'RegisterBindings.rs'),
+ ('InterfaceTypes', 'InterfaceTypes.rs'),
+ ('InheritTypes', 'InheritTypes.rs'),
+ ('Bindings', 'Bindings/mod.rs'),
+ ('UnionTypes', 'UnionTypes.rs'),
+ ]
+
+ for name, filename in to_generate:
+ generate_file(config, name, os.path.join(outputdir, filename))
if __name__ == '__main__':
main()
diff --git a/components/script/dom/bindings/codegen/pythonpath.py b/components/script/dom/bindings/codegen/pythonpath.py
deleted file mode 100644
index 793089551b5..00000000000
--- a/components/script/dom/bindings/codegen/pythonpath.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# 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/.
-
-"""
-Run a python script, adding extra directories to the python path.
-"""
-
-
-def main(args):
- def usage():
- print >>sys.stderr, "pythonpath.py -I directory script.py [args...]"
- sys.exit(150)
-
- paths = []
-
- while True:
- try:
- arg = args[0]
- except IndexError:
- usage()
-
- if arg == '-I':
- args.pop(0)
- try:
- path = args.pop(0)
- except IndexError:
- usage()
-
- paths.append(os.path.abspath(path))
- continue
-
- if arg.startswith('-I'):
- paths.append(os.path.abspath(args.pop(0)[2:]))
- continue
-
- if arg.startswith('-D'):
- os.chdir(args.pop(0)[2:])
- continue
-
- break
-
- script = args[0]
-
- sys.path[0:0] = [os.path.abspath(os.path.dirname(script))] + paths
- sys.argv = args
- sys.argc = len(args)
-
- frozenglobals['__name__'] = '__main__'
- frozenglobals['__file__'] = script
-
- execfile(script, frozenglobals)
-
-# Freeze scope here ... why this makes things work I have no idea ...
-frozenglobals = globals()
-
-import sys
-import os
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs
index 283dc9b08c9..1ded213d0f4 100644
--- a/components/script/dom/bindings/mod.rs
+++ b/components/script/dom/bindings/mod.rs
@@ -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"));
}
diff --git a/components/script/dom/bindings/num.rs b/components/script/dom/bindings/num.rs
index 87c5e38a3bb..1169ccdec7f 100644
--- a/components/script/dom/bindings/num.rs
+++ b/components/script/dom/bindings/num.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> {}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index b1dcbbce163..8e48de2c680 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -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| {
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs
index e44e17d39de..247de62b23f 100644
--- a/components/script/dom/cssstyledeclaration.rs
+++ b/components/script/dom/cssstyledeclaration.rs
@@ -334,5 +334,6 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
rval
}
+ // https://drafts.csswg.org/cssom/#cssstyledeclaration
css_properties_accessors!(css_properties);
}
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index bc179a82133..d4a3b216914 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -357,6 +357,7 @@ impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
Ok(())
}
+ // https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage
event_handler!(message, GetOnmessage, SetOnmessage);
}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 0ff28055e9d..196ea7af438 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -1842,7 +1842,10 @@ impl DocumentMethods for Document {
// This method intentionally does nothing
}
+ // https://html.spec.whatwg.org/multipage/#globaleventhandlers
global_event_handlers!();
+
+ // https://html.spec.whatwg.org/multipage/#handler-onreadystatechange
event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange);
}
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 83b7c24ed3a..4e03dff4086 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -1867,10 +1867,10 @@ impl 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);
diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs
index 384ab976be3..ffd74806c04 100644
--- a/components/script/dom/filereader.rs
+++ b/components/script/dom/filereader.rs
@@ -253,11 +253,22 @@ impl 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
diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs
index 8390430c39e..8631cefbd4a 100644
--- a/components/script/dom/formdata.rs
+++ b/components/script/dom/formdata.rs
@@ -85,21 +85,14 @@ impl FormDataMethods for FormData {
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
- }
+ 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
diff --git a/components/script/dom/htmlappletelement.rs b/components/script/dom/htmlappletelement.rs
index a3cb281497b..988aa36e9ee 100644
--- a/components/script/dom/htmlappletelement.rs
+++ b/components/script/dom/htmlappletelement.rs
@@ -54,6 +54,8 @@ impl 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");
}
diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs
index a38e385bc9c..3016966fc10 100644
--- a/components/script/dom/htmlbodyelement.rs
+++ b/components/script/dom/htmlbodyelement.rs
@@ -71,6 +71,8 @@ impl 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
diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs
index a8c95eb6d3b..c7f3e71807e 100644
--- a/components/script/dom/htmlbuttonelement.rs
+++ b/components/script/dom/htmlbuttonelement.rs
@@ -98,22 +98,29 @@ impl HTMLButtonElementMethods for 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
diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs
index 6aee8645ad8..ad16e70afa2 100644
--- a/components/script/dom/htmlcollection.rs
+++ b/components/script/dom/htmlcollection.rs
@@ -64,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)
}
diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs
index 0b9ea1e6b8c..80e6f93d36e 100644
--- a/components/script/dom/htmlelement.rs
+++ b/components/script/dom/htmlelement.rs
@@ -130,16 +130,22 @@ impl HTMLElementMethods for HTMLElement {
})
}
+ // 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
diff --git a/components/script/dom/htmlfontelement.rs b/components/script/dom/htmlfontelement.rs
index 03750d382b8..6b745617b94 100644
--- a/components/script/dom/htmlfontelement.rs
+++ b/components/script/dom/htmlfontelement.rs
@@ -50,7 +50,10 @@ impl HTMLFontElement {
}
impl HTMLFontElementMethods for HTMLFontElement {
+ // https://html.spec.whatwg.org/multipage/#dom-font-color
make_getter!(Color, "color");
+
+ // https://html.spec.whatwg.org/multipage/#dom-font-color
make_setter!(SetColor, "color");
}
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 11613d866b2..05f7442bbcc 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -122,6 +122,8 @@ impl HTMLFormElementMethods for HTMLFormElement {
// https://html.spec.whatwg.org/multipage/#dom-form-name
make_getter!(Name);
+
+ // https://html.spec.whatwg.org/multipage/#dom-form-name
make_atomic_setter!(SetName, "name");
// https://html.spec.whatwg.org/multipage/#dom-fs-novalidate
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index 6abf4f7b877..e4665847468 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -339,12 +339,14 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
Err(NotSupported)
}
+ // https://html.spec.whatwg.org/multipage/#dom-dim-width
make_getter!(Width);
-
+ // https://html.spec.whatwg.org/multipage/#dom-dim-width
make_setter!(SetWidth, "width");
+ // https://html.spec.whatwg.org/multipage/#dom-dim-height
make_getter!(Height);
-
+ // https://html.spec.whatwg.org/multipage/#dom-dim-height
make_setter!(SetHeight, "height");
}
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index dcb69a44104..bfd6ca2fdd8 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -197,18 +197,22 @@ impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
}
impl HTMLImageElementMethods for HTMLImageElement {
+ // https://html.spec.whatwg.org/multipage/#dom-img-alt
make_getter!(Alt);
-
+ // https://html.spec.whatwg.org/multipage/#dom-img-alt
make_setter!(SetAlt, "alt");
+ // https://html.spec.whatwg.org/multipage/#dom-img-src
make_url_getter!(Src);
-
+ // https://html.spec.whatwg.org/multipage/#dom-img-src
make_setter!(SetSrc, "src");
+ // https://html.spec.whatwg.org/multipage/#dom-img-usemap
make_getter!(UseMap);
-
+ // https://html.spec.whatwg.org/multipage/#dom-img-usemap
make_setter!(SetUseMap, "usemap");
+ // https://html.spec.whatwg.org/multipage/#dom-img-ismap
make_bool_getter!(IsMap);
// https://html.spec.whatwg.org/multipage/#dom-img-ismap
@@ -269,28 +273,40 @@ impl HTMLImageElementMethods for HTMLImageElement {
image.is_some()
}
- // https://html.spec.whatwg.org/#dom-img-name
+ // https://html.spec.whatwg.org/multipage/#dom-img-name
make_getter!(Name);
+
+ // https://html.spec.whatwg.org/multipage/#dom-img-name
make_atomic_setter!(SetName, "name");
+ // https://html.spec.whatwg.org/multipage/#dom-img-align
make_getter!(Align);
+ // https://html.spec.whatwg.org/multipage/#dom-img-align
make_setter!(SetAlign, "align");
+ // https://html.spec.whatwg.org/multipage/#dom-img-hspace
make_uint_getter!(Hspace);
+ // https://html.spec.whatwg.org/multipage/#dom-img-hspace
make_uint_setter!(SetHspace, "hspace");
+ // https://html.spec.whatwg.org/multipage/#dom-img-vspace
make_uint_getter!(Vspace);
+ // https://html.spec.whatwg.org/multipage/#dom-img-vspace
make_uint_setter!(SetVspace, "vspace");
+ // https://html.spec.whatwg.org/multipage/#dom-img-longdesc
make_getter!(LongDesc);
+ // https://html.spec.whatwg.org/multipage/#dom-img-longdesc
make_setter!(SetLongDesc, "longdesc");
+ // https://html.spec.whatwg.org/multipage/#dom-img-border
make_getter!(Border);
+ // https://html.spec.whatwg.org/multipage/#dom-img-border
make_setter!(SetBorder, "border");
}
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index becbf7c4947..9204e20ab22 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -247,6 +247,8 @@ impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#dom-input-size
make_uint_getter!(Size, "size", DEFAULT_INPUT_SIZE);
+
+ // https://html.spec.whatwg.org/multipage/#dom-input-size
make_limited_uint_setter!(SetSize, "size", DEFAULT_INPUT_SIZE);
// https://html.spec.whatwg.org/multipage/#dom-input-type
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 072e14bab3b..b9e3d0e081b 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -209,19 +209,34 @@ impl HTMLLinkElement {
}
impl HTMLLinkElementMethods for HTMLLinkElement {
+ // https://html.spec.whatwg.org/multipage/#dom-link-href
make_url_getter!(Href);
+
+ // https://html.spec.whatwg.org/multipage/#dom-link-href
make_setter!(SetHref, "href");
+ // https://html.spec.whatwg.org/multipage/#dom-link-rel
make_getter!(Rel);
+
+ // https://html.spec.whatwg.org/multipage/#dom-link-rel
make_setter!(SetRel, "rel");
+ // https://html.spec.whatwg.org/multipage/#dom-link-media
make_getter!(Media);
+
+ // https://html.spec.whatwg.org/multipage/#dom-link-media
make_setter!(SetMedia, "media");
+ // https://html.spec.whatwg.org/multipage/#dom-link-hreflang
make_getter!(Hreflang);
+
+ // https://html.spec.whatwg.org/multipage/#dom-link-hreflang
make_setter!(SetHreflang, "hreflang");
+ // https://html.spec.whatwg.org/multipage/#dom-link-type
make_getter!(Type);
+
+ // https://html.spec.whatwg.org/multipage/#dom-link-type
make_setter!(SetType, "type");
// https://html.spec.whatwg.org/multipage/#dom-link-rellist
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 82908e2d78f..97cd6573fda 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -571,8 +571,9 @@ impl VirtualMethods for HTMLScriptElement {
}
impl HTMLScriptElementMethods for HTMLScriptElement {
+ // https://html.spec.whatwg.org/multipage/#dom-script-src
make_url_getter!(Src);
-
+ // https://html.spec.whatwg.org/multipage/#dom-script-src
make_setter!(SetSrc, "src");
// https://www.whatwg.org/html/#dom-script-text
diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs
index 153593f5e58..db4a08a00c5 100644
--- a/components/script/dom/htmltablecellelement.rs
+++ b/components/script/dom/htmltablecellelement.rs
@@ -77,6 +77,8 @@ impl HTMLTableCellElement {
impl HTMLTableCellElementMethods for HTMLTableCellElement {
// https://html.spec.whatwg.org/multipage/#dom-tdth-colspan
make_uint_getter!(ColSpan, "colspan", DEFAULT_COLSPAN);
+
+ // https://html.spec.whatwg.org/multipage/#dom-tdth-colspan
make_uint_setter!(SetColSpan, "colspan");
}
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index 333e5259394..a0a0c12b705 100644
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -121,6 +121,8 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// https://html.spec.whatwg.org/multipage/#dom-textarea-cols
make_uint_getter!(Cols, "cols", DEFAULT_COLS);
+
+ // https://html.spec.whatwg.org/multipage/#dom-textarea-cols
make_limited_uint_setter!(SetCols, "cols", DEFAULT_COLS);
// https://www.whatwg.org/html/#dom-fe-disabled
@@ -155,6 +157,8 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// https://html.spec.whatwg.org/multipage/#dom-textarea-rows
make_uint_getter!(Rows, "rows", DEFAULT_ROWS);
+
+ // https://html.spec.whatwg.org/multipage/#dom-textarea-rows
make_limited_uint_setter!(SetRows, "rows", DEFAULT_ROWS);
// https://html.spec.whatwg.org/multipage/#dom-textarea-wrap
diff --git a/components/script/dom/location.rs b/components/script/dom/location.rs
index 22c250bbb55..8b5cf37965e 100644
--- a/components/script/dom/location.rs
+++ b/components/script/dom/location.rs
@@ -4,6 +4,7 @@
use dom::bindings::codegen::Bindings::LocationBinding;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
+use dom::bindings::error::ErrorResult;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root};
use dom::bindings::str::USVString;
@@ -33,6 +34,18 @@ impl Location {
GlobalRef::Window(window),
LocationBinding::Wrap)
}
+
+ fn get_url(&self) -> Url {
+ self.window.root().get_url()
+ }
+
+ fn set_url_component(&self, value: USVString,
+ setter: fn(&mut Url, USVString)) {
+ let window = self.window.root();
+ let mut url = window.get_url();
+ setter(&mut url, value);
+ window.load_url(url);
+ }
}
impl LocationMethods for Location {
@@ -52,9 +65,9 @@ impl LocationMethods for Location {
UrlHelper::Hash(&self.get_url())
}
- // https://url.spec.whatwg.org/#dom-urlutils-href
- fn Href(&self) -> USVString {
- UrlHelper::Href(&self.get_url())
+ // https://url.spec.whatwg.org/#dom-urlutils-hash
+ fn SetHash(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetHash);
}
// https://url.spec.whatwg.org/#dom-urlutils-host
@@ -62,31 +75,75 @@ impl LocationMethods for Location {
UrlHelper::Host(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-host
+ fn SetHost(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetHost);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-hostname
fn Hostname(&self) -> USVString {
UrlHelper::Hostname(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-hostname
+ fn SetHostname(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetHostname);
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-href
+ fn Href(&self) -> USVString {
+ UrlHelper::Href(&self.get_url())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-href
+ fn SetHref(&self, value: USVString) -> ErrorResult {
+ let window = self.window.root();
+ if let Ok(url) = UrlParser::new().base_url(&window.get_url()).parse(&value.0) {
+ window.load_url(url);
+ };
+ Ok(())
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-password
fn Password(&self) -> USVString {
UrlHelper::Password(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-password
+ fn SetPassword(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetPassword);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-pathname
fn Pathname(&self) -> USVString {
UrlHelper::Pathname(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-pathname
+ fn SetPathname(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetPathname);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-port
fn Port(&self) -> USVString {
UrlHelper::Port(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-port
+ fn SetPort(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetPort);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-protocol
fn Protocol(&self) -> USVString {
UrlHelper::Protocol(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-protocol
+ fn SetProtocol(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetProtocol);
+ }
+
// https://url.spec.whatwg.org/#URLUtils-stringification-behavior
fn Stringifier(&self) -> DOMString {
self.Href().0
@@ -97,16 +154,18 @@ impl LocationMethods for Location {
UrlHelper::Search(&self.get_url())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-search
+ fn SetSearch(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetSearch);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-username
fn Username(&self) -> USVString {
UrlHelper::Username(&self.get_url())
}
-}
-
-impl Location {
- fn get_url(&self) -> Url {
- let window = self.window.root();
- window.r().get_url()
+ // https://url.spec.whatwg.org/#dom-urlutils-username
+ fn SetUsername(&self, value: USVString) {
+ self.set_url_component(value, UrlHelper::SetUsername);
}
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index ac21c9eefc2..f46cbc0be11 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -1629,8 +1629,7 @@ impl Node {
Node::adopt(node, &*parent.owner_doc());
}
// Step 2.
- let mut removed_nodes = RootedVec::new();
- removed_nodes.extend(parent.children().map(|child| JS::from_rooted(&child)));
+ let removed_nodes = parent.children().collect::<RootedVec<_>>();
// Step 3.
let mut added_nodes = RootedVec::new();
let added_nodes = if let Some(node) = node.as_ref() {
diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs
index 01bc27d3a08..3e2bc5145c6 100644
--- a/components/script/dom/nodelist.rs
+++ b/components/script/dom/nodelist.rs
@@ -215,7 +215,10 @@ impl ChildrenList {
},
};
list.last_visited.set(Some(JS::from_ref(visited)));
- } else {
+ } else if added.len() != 1 {
+ // The replaced child isn't the last visited one, and there are
+ // 0 or more than 1 nodes to replace it. Special care must be
+ // given to update the state of that ChildrenList.
match (prev, next) {
(Some(_), None) => {},
(None, Some(next)) => {
diff --git a/components/script/dom/progressevent.rs b/components/script/dom/progressevent.rs
index 88a369606ae..b715330edae 100644
--- a/components/script/dom/progressevent.rs
+++ b/components/script/dom/progressevent.rs
@@ -52,9 +52,9 @@ impl ProgressEvent {
type_: DOMString,
init: &ProgressEventBinding::ProgressEventInit)
-> Fallible<Root<ProgressEvent>> {
- let bubbles = if init.parent.bubbles {EventBubbles::Bubbles} else {EventBubbles::DoesNotBubble};
- let cancelable = if init.parent.cancelable {EventCancelable::Cancelable}
- else {EventCancelable::NotCancelable};
+ let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble };
+ let cancelable = if init.parent.cancelable { EventCancelable::Cancelable }
+ else { EventCancelable::NotCancelable };
let ev = ProgressEvent::new(global, type_, bubbles, cancelable,
init.lengthComputable, init.loaded, init.total);
Ok(ev)
diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs
index 335e261634b..e050f799c8f 100644
--- a/components/script/dom/testbinding.rs
+++ b/components/script/dom/testbinding.rs
@@ -120,6 +120,10 @@ impl TestBindingMethods for TestBinding {
fn SetBinaryRenamedAttribute(&self, _: DOMString) {}
fn ForwardedAttribute(&self) -> Root<TestBinding> { Root::from_ref(self) }
fn BinaryRenamedAttribute(&self) -> DOMString { "".to_owned() }
+ fn SetBinaryRenamedAttribute2(&self, _: DOMString) {}
+ fn BinaryRenamedAttribute2(&self) -> DOMString { "".to_owned() }
+ fn Attr_to_automatically_rename(&self) -> DOMString { "".to_owned() }
+ fn SetAttr_to_automatically_rename(&self, _: DOMString) {}
fn GetEnumAttributeNullable(&self) -> Option<TestEnum> { Some(_empty) }
fn GetInterfaceAttributeNullable(&self) -> Option<Root<Blob>> {
let global = self.global.root();
diff --git a/components/script/dom/testbindingproxy.rs b/components/script/dom/testbindingproxy.rs
index 3c1f23c8ae1..5ca27eae735 100644
--- a/components/script/dom/testbindingproxy.rs
+++ b/components/script/dom/testbindingproxy.rs
@@ -15,20 +15,20 @@ pub struct TestBindingProxy {
}
impl TestBindingProxyMethods for TestBindingProxy {
- fn Length(&self) -> u32 {0}
- fn SupportedPropertyNames(&self) -> Vec<DOMString> {vec![]}
- fn GetNamedItem(&self, _: DOMString) -> DOMString {"".to_owned()}
+ fn Length(&self) -> u32 { 0 }
+ fn SupportedPropertyNames(&self) -> Vec<DOMString> { vec![] }
+ fn GetNamedItem(&self, _: DOMString) -> DOMString { "".to_owned() }
fn SetNamedItem(&self, _: DOMString, _: DOMString) -> () {}
- fn GetItem(&self, _: u32) -> DOMString {"".to_owned()}
+ fn GetItem(&self, _: u32) -> DOMString { "".to_owned() }
fn SetItem(&self, _: u32, _: DOMString) -> () {}
fn RemoveItem(&self, _: DOMString) -> () {}
- fn Stringifier(&self) -> DOMString {"".to_owned()}
+ fn Stringifier(&self) -> DOMString { "".to_owned() }
fn NamedCreator(&self, _: DOMString, _: DOMString) -> () {}
- fn IndexedGetter(&self, _: u32, _: &mut bool) -> DOMString {"".to_owned()}
+ fn IndexedGetter(&self, _: u32, _: &mut bool) -> DOMString { "".to_owned() }
fn NamedDeleter(&self, _: DOMString) -> () {}
fn IndexedSetter(&self, _: u32, _: DOMString) -> () {}
fn NamedSetter(&self, _: DOMString, _: DOMString) -> () {}
fn IndexedCreator(&self, _: u32, _: DOMString) -> () {}
- fn NamedGetter(&self, _: DOMString, _: &mut bool) -> DOMString {"".to_owned()}
+ fn NamedGetter(&self, _: DOMString, _: &mut bool) -> DOMString { "".to_owned() }
}
diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs
index ec44fe2fdf9..f34428d4bbb 100644
--- a/components/script/dom/url.rs
+++ b/components/script/dom/url.rs
@@ -3,17 +3,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::Bindings::URLBinding::{self, URLMethods};
-use dom::bindings::error::{Error, Fallible};
+use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::str::USVString;
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::urlhelper::UrlHelper;
-use url::{Host, Url, UrlParser};
+use url::{Host, ParseResult, Url, UrlParser};
use util::str::DOMString;
use std::borrow::ToOwned;
+use std::cell::RefCell;
// https://url.spec.whatwg.org/#url
#[dom_struct]
@@ -21,19 +22,23 @@ pub struct URL {
reflector_: Reflector,
// https://url.spec.whatwg.org/#concept-urlutils-url
- url: Url,
+ url: RefCell<Url>,
+
+ // https://url.spec.whatwg.org/#concept-urlutils-get-the-base
+ base: Option<Url>,
}
impl URL {
- fn new_inherited(url: Url) -> URL {
+ fn new_inherited(url: Url, base: Option<Url>) -> URL {
URL {
reflector_: Reflector::new(),
- url: url,
+ url: RefCell::new(url),
+ base: base,
}
}
- pub fn new(global: GlobalRef, url: Url) -> Root<URL> {
- reflect_dom_object(box URL::new_inherited(url),
+ pub fn new(global: GlobalRef, url: Url, base: Option<Url>) -> Root<URL> {
+ reflect_dom_object(box URL::new_inherited(url, base),
global, URLBinding::Wrap)
}
}
@@ -59,7 +64,7 @@ impl URL {
}
};
// Step 3.
- let parsed_url = match parser_with_base(parsed_base.as_ref()).parse(&url.0) {
+ let parsed_url = match parse_with_base(url, parsed_base.as_ref()) {
Ok(url) => url,
Err(error) => {
// Step 4.
@@ -67,7 +72,7 @@ impl URL {
}
};
// Steps 5-8.
- Ok(URL::new(global, parsed_url))
+ Ok(URL::new(global, parsed_url, parsed_base))
}
// https://url.spec.whatwg.org/#dom-url-domaintoasciidomain
@@ -87,47 +92,100 @@ impl URL {
impl URLMethods for URL {
// https://url.spec.whatwg.org/#dom-urlutils-hash
fn Hash(&self) -> USVString {
- UrlHelper::Hash(&self.url)
+ UrlHelper::Hash(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-hash
+ fn SetHash(&self, value: USVString) {
+ UrlHelper::SetHash(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-host
fn Host(&self) -> USVString {
- UrlHelper::Host(&self.url)
+ UrlHelper::Host(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-host
+ fn SetHost(&self, value: USVString) {
+ UrlHelper::SetHost(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-hostname
fn Hostname(&self) -> USVString {
- UrlHelper::Hostname(&self.url)
+ UrlHelper::Hostname(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-hostname
+ fn SetHostname(&self, value: USVString) {
+ UrlHelper::SetHostname(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-href
fn Href(&self) -> USVString {
- UrlHelper::Href(&self.url)
+ UrlHelper::Href(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-href
+ fn SetHref(&self, value: USVString) -> ErrorResult {
+ match parse_with_base(value, self.base.as_ref()) {
+ Ok(url) => {
+ *self.url.borrow_mut() = url;
+ Ok(())
+ },
+ Err(error) => {
+ Err(Error::Type(format!("could not parse URL: {}", error)))
+ },
+ }
}
// https://url.spec.whatwg.org/#dom-urlutils-password
fn Password(&self) -> USVString {
- UrlHelper::Password(&self.url)
+ UrlHelper::Password(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-password
+ fn SetPassword(&self, value: USVString) {
+ UrlHelper::SetPassword(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-pathname
fn Pathname(&self) -> USVString {
- UrlHelper::Pathname(&self.url)
+ UrlHelper::Pathname(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-pathname
+ fn SetPathname(&self, value: USVString) {
+ UrlHelper::SetPathname(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-port
fn Port(&self) -> USVString {
- UrlHelper::Port(&self.url)
+ UrlHelper::Port(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-port
+ fn SetPort(&self, value: USVString) {
+ UrlHelper::SetPort(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-protocol
fn Protocol(&self) -> USVString {
- UrlHelper::Protocol(&self.url)
+ UrlHelper::Protocol(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-protocol
+ fn SetProtocol(&self, value: USVString) {
+ UrlHelper::SetProtocol(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#dom-urlutils-search
fn Search(&self) -> USVString {
- UrlHelper::Search(&self.url)
+ UrlHelper::Search(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-search
+ fn SetSearch(&self, value: USVString) {
+ UrlHelper::SetSearch(&mut self.url.borrow_mut(), value);
}
// https://url.spec.whatwg.org/#URLUtils-stringification-behavior
@@ -137,14 +195,19 @@ impl URLMethods for URL {
// https://url.spec.whatwg.org/#dom-urlutils-username
fn Username(&self) -> USVString {
- UrlHelper::Username(&self.url)
+ UrlHelper::Username(&self.url.borrow())
+ }
+
+ // https://url.spec.whatwg.org/#dom-urlutils-username
+ fn SetUsername(&self, value: USVString) {
+ UrlHelper::SetUsername(&mut self.url.borrow_mut(), value);
}
}
-fn parser_with_base(base: Option<&Url>) -> UrlParser {
+fn parse_with_base(input: USVString, base: Option<&Url>) -> ParseResult<Url> {
let mut parser = UrlParser::new();
if let Some(base) = base {
parser.base_url(base);
}
- parser
+ parser.parse(&input.0)
}
diff --git a/components/script/dom/urlhelper.rs b/components/script/dom/urlhelper.rs
index 4376a85e390..684d6666e0c 100644
--- a/components/script/dom/urlhelper.rs
+++ b/components/script/dom/urlhelper.rs
@@ -4,7 +4,9 @@
use dom::bindings::str::USVString;
-use url::{Url, SchemeData};
+use url::{Url, UrlParser, SchemeData};
+
+use url::urlutils::{UrlUtils, UrlUtilsWrapper};
use std::borrow::ToOwned;
use std::fmt::Write;
@@ -22,6 +24,12 @@ impl UrlHelper {
})
}
+ // https://url.spec.whatwg.org/#dom-urlutils-hash
+ pub fn SetHash(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_fragment(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-host
pub fn Host(url: &Url) -> USVString {
USVString(match url.scheme_data {
@@ -36,11 +44,23 @@ impl UrlHelper {
})
}
+ // https://url.spec.whatwg.org/#dom-urlutils-host
+ pub fn SetHost(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_host(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-hostname
pub fn Hostname(url: &Url) -> USVString {
USVString(url.serialize_host().unwrap_or_else(|| "".to_owned()))
}
+ // https://url.spec.whatwg.org/#dom-urlutils-hostname
+ pub fn SetHostname(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_host_and_port(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-href
pub fn Href(url: &Url) -> USVString {
USVString(url.serialize())
@@ -51,15 +71,26 @@ impl UrlHelper {
USVString(url.password().unwrap_or("").to_owned())
}
+ // https://url.spec.whatwg.org/#dom-urlutils-password
+ pub fn SetPassword(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_password(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-pathname
pub fn Pathname(url: &Url) -> USVString {
- // FIXME: Url null check is skipped for now
USVString(match url.scheme_data {
SchemeData::NonRelative(ref scheme_data) => scheme_data.clone(),
SchemeData::Relative(..) => url.serialize_path().unwrap()
})
}
+ // https://url.spec.whatwg.org/#dom-urlutils-pathname
+ pub fn SetPathname(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_path(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-port
pub fn Port(url: &Url) -> USVString {
USVString(match url.port() {
@@ -68,11 +99,23 @@ impl UrlHelper {
})
}
+ // https://url.spec.whatwg.org/#dom-urlutils-port
+ pub fn SetPort(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_port(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-protocol
pub fn Protocol(url: &Url) -> USVString {
USVString(format!("{}:", url.scheme.clone()))
}
+ // https://url.spec.whatwg.org/#dom-urlutils-protocol
+ pub fn SetProtocol(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_scheme(&value.0);
+ }
+
// https://html.spec.whatwg.org/multipage/#same-origin
pub fn SameOrigin(urlA: &Url, urlB: &Url) -> bool {
if urlA.host() != urlB.host() {
@@ -96,8 +139,20 @@ impl UrlHelper {
})
}
+ // https://url.spec.whatwg.org/#dom-urlutils-search
+ pub fn SetSearch(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_query(&value.0);
+ }
+
// https://url.spec.whatwg.org/#dom-urlutils-username
pub fn Username(url: &Url) -> USVString {
USVString(url.username().unwrap_or("").to_owned())
}
+
+ // https://url.spec.whatwg.org/#dom-urlutils-username
+ pub fn SetUsername(url: &mut Url, value: USVString) {
+ let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
+ let _ = wrapper.set_username(&value.0);
+ }
}
diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs
index 3920bcb7b7c..bcad061853f 100644
--- a/components/script/dom/webglshader.rs
+++ b/components/script/dom/webglshader.rs
@@ -11,10 +11,19 @@ use dom::webglobject::WebGLObject;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
+use angle::hl::{BuiltInResources, Output, ShaderValidator};
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLResult, WebGLError, WebGLShaderParameter};
use ipc_channel::ipc::{self, IpcSender};
use std::cell::Cell;
use std::cell::RefCell;
+use std::sync::{Once, ONCE_INIT};
+
+#[derive(Clone, Copy, PartialEq, Debug, JSTraceable, HeapSizeOf)]
+pub enum ShaderCompilationStatus {
+ NotCompiled,
+ Succeeded,
+ Failed,
+}
#[dom_struct]
pub struct WebGLShader {
@@ -22,20 +31,32 @@ pub struct WebGLShader {
id: u32,
gl_type: u32,
source: RefCell<Option<String>>,
+ info_log: RefCell<Option<String>>,
is_deleted: Cell<bool>,
- // TODO(ecoal95): Evaluate moving this to `WebGLObject`
+ compilation_status: Cell<ShaderCompilationStatus>,
#[ignore_heap_size_of = "Defined in ipc-channel"]
renderer: IpcSender<CanvasMsg>,
}
+#[cfg(not(target_os = "android"))]
+const SHADER_OUTPUT_FORMAT: Output = Output::Glsl;
+
+#[cfg(target_os = "android")]
+const SHADER_OUTPUT_FORMAT: Output = Output::Essl;
+
+static GLSLANG_INITIALIZATION: Once = ONCE_INIT;
+
impl WebGLShader {
fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32, shader_type: u32) -> WebGLShader {
+ GLSLANG_INITIALIZATION.call_once(|| ::angle::hl::initialize().unwrap());
WebGLShader {
webgl_object: WebGLObject::new_inherited(),
id: id,
gl_type: shader_type,
source: RefCell::new(None),
+ info_log: RefCell::new(None),
is_deleted: Cell::new(false),
+ compilation_status: Cell::new(ShaderCompilationStatus::NotCompiled),
renderer: renderer,
}
}
@@ -69,10 +90,33 @@ impl WebGLShader {
self.gl_type
}
- // TODO(ecoal95): Validate shaders to be conforming to the WebGL spec
/// glCompileShader
pub fn compile(&self) {
- self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CompileShader(self.id))).unwrap()
+ if self.compilation_status.get() != ShaderCompilationStatus::NotCompiled {
+ debug!("Compiling already compiled shader {}", self.id);
+ }
+
+ if let Some(ref source) = *self.source.borrow() {
+ let validator = ShaderValidator::for_webgl(self.gl_type,
+ SHADER_OUTPUT_FORMAT,
+ &BuiltInResources::default()).unwrap();
+ match validator.compile_and_translate(&[source.as_bytes()]) {
+ Ok(translated_source) => {
+ // NOTE: At this point we should be pretty sure that the compilation in the paint task
+ // will succeed.
+ // It could be interesting to retrieve the info log from the paint task though
+ let msg = CanvasWebGLMsg::CompileShader(self.id, translated_source);
+ self.renderer.send(CanvasMsg::WebGL(msg)).unwrap();
+ self.compilation_status.set(ShaderCompilationStatus::Succeeded);
+ },
+ Err(error) => {
+ self.compilation_status.set(ShaderCompilationStatus::Failed);
+ debug!("Shader {} compilation failed: {}", self.id, error);
+ },
+ }
+
+ *self.info_log.borrow_mut() = Some(validator.info_log());
+ }
}
/// Mark this shader as deleted (if it wasn't previously)
@@ -86,9 +130,7 @@ impl WebGLShader {
/// glGetShaderInfoLog
pub fn info_log(&self) -> Option<String> {
- let (sender, receiver) = ipc::channel().unwrap();
- self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetShaderInfoLog(self.id, sender))).unwrap();
- receiver.recv().unwrap()
+ self.info_log.borrow().clone()
}
/// glGetShaderParameter
@@ -110,7 +152,6 @@ impl WebGLShader {
/// glShaderSource
pub fn set_source(&self, source: String) {
- *self.source.borrow_mut() = Some(source.clone());
- self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::ShaderSource(self.id, source))).unwrap()
+ *self.source.borrow_mut() = Some(source);
}
}
diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl
index 014e12740bf..dba69a515b0 100644
--- a/components/script/dom/webidls/CSSStyleDeclaration.webidl
+++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl
@@ -34,40 +34,73 @@ interface CSSStyleDeclaration {
partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString background;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundPosition;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-position;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundRepeat;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-repeat;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundImage;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-image;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundAttachment;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-attachment;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundOrigin;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-origin;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundClip;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-clip;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString border;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderRadius;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-radius;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderSpacing;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-spacing;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBottom;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-bottom;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBottomColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-bottom-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBottomLeftRadius;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-bottom-left-radius;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBottomRightRadius;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-bottom-right-radius;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBottomStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-bottom-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderBottomWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-bottom-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderLeft;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-left;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderLeftColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-left-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderLeftStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-left-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderLeftWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-left-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderRight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderRightColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-right-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderRightStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-right-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderRightWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-right-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTop;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopLeftRadius;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-left-radius;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopRightRadius;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-right-radius;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderTopWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-top-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString content;
@@ -82,8 +115,11 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString cursor;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString boxSizing;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString box-sizing;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString boxShadow;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString box-shadow;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textShadow;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-shadow;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString _float;
@@ -93,89 +129,143 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transformOrigin;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform-origin;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString perspective;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString perspectiveOrigin;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString perspective-origin;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transformStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString backfaceVisibility;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString backface-visibility;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString direction;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString unicodeBidi;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString unicode-bidi;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString filter;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString lineHeight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString line-height;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString mixBlendMode;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString mix-blend-mode;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString verticalAlign;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString vertical-align;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString listStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString list-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString listStylePosition;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString list-style-position;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString listStyleType;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString list-style-type;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString listStyleImage;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString list-style-image;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString quotes;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString counterIncrement;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString counter-increment;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString counterReset;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString counter-reset;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflow;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflowX;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflow-x;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflowY;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflow-y;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflowWrap;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString overflow-wrap;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString tableLayout;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString table-layout;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString borderCollapse;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString border-collapse;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString emptyCells;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString empty-cells;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString captionSide;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString caption-side;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString whiteSpace;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString white-space;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString writingMode;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString writing-mode;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString letterSpacing;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString letter-spacing;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString wordBreak;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString word-break;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString wordSpacing;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString word-spacing;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString wordWrap;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString word-wrap;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textOverflow;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-overflow;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textAlign;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-align;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textDecoration;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-decoration;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textIndent;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-indent;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textJustify;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-justify;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textOrientation;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-orientation;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textRendering;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-rendering;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString textTransform;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString text-transform;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString font;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontFamily;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-family;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontSize;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-size;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontStretch;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-stretch;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontVariant;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-variant;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString fontWeight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString font-weight;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginBottom;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-bottom;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginLeft;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-left;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginRight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString marginTop;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString margin-top;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingBottom;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-bottom;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingLeft;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-left;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingRight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-right;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString paddingTop;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString padding-top;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineColor;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline-color;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineStyle;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline-style;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString outlineOffset;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString outline-offset;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString position;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString pointerEvents;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString pointer-events;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString top;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString right;
@@ -184,26 +274,40 @@ partial interface CSSStyleDeclaration {
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString height;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString minHeight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-height;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxHeight;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-height;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString minWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString min-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString maxWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString max-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString zIndex;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString z-index;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString imageRendering;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString image-rendering;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString columnCount;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString column-count;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString columnWidth;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString column-width;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString columns;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString columnGap;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString column-gap;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transition;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transitionDuration;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString transition-duration;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transitionTimingFunction;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString transition-timing-function;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transitionProperty;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString transition-property;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString transitionDelay;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString transition-delay;
[SetterThrows, TreatNullAs=EmptyString] attribute DOMString flexDirection;
+ [SetterThrows, TreatNullAs=EmptyString] attribute DOMString flex-direction;
};
diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl
index 08221f2ccc0..181909721aa 100644
--- a/components/script/dom/webidls/TestBinding.webidl
+++ b/components/script/dom/webidls/TestBinding.webidl
@@ -115,6 +115,8 @@ interface TestBinding {
attribute (HTMLElement or long)? unionAttributeNullable;
attribute (Event or DOMString)? union2AttributeNullable;
[BinaryName="BinaryRenamedAttribute"] attribute DOMString attrToBinaryRename;
+ [BinaryName="BinaryRenamedAttribute2"] attribute DOMString attr-to-binary-rename;
+ attribute DOMString attr-to-automatically-rename;
[PutForwards=booleanAttribute]
readonly attribute TestBinding forwardedAttribute;
diff --git a/components/script/dom/webidls/URLUtils.webidl b/components/script/dom/webidls/URLUtils.webidl
index 86e5140311b..1b8965f3d37 100644
--- a/components/script/dom/webidls/URLUtils.webidl
+++ b/components/script/dom/webidls/URLUtils.webidl
@@ -7,27 +7,19 @@
[NoInterfaceObject]
interface URLUtils {
//stringifier attribute USVString href;
- readonly attribute USVString href;
+ [SetterThrows]
+ attribute USVString href;
//readonly attribute USVString origin;
- // attribute USVString protocol;
- readonly attribute USVString protocol;
- // attribute USVString username;
- readonly attribute USVString username;
- // attribute USVString password;
- readonly attribute USVString password;
- // attribute USVString host;
- readonly attribute USVString host;
- // attribute USVString hostname;
- readonly attribute USVString hostname;
- // attribute USVString port;
- readonly attribute USVString port;
- // attribute USVString pathname;
- readonly attribute USVString pathname;
- // attribute USVString search;
- readonly attribute USVString search;
+ attribute USVString protocol;
+ attribute USVString username;
+ attribute USVString password;
+ attribute USVString host;
+ attribute USVString hostname;
+ attribute USVString port;
+ attribute USVString pathname;
+ attribute USVString search;
// attribute URLSearchParams searchParams;
- // attribute USVString hash;
- readonly attribute USVString hash;
+ attribute USVString hash;
// This is only doing as well as gecko right now, bug 824857 is on file for
// adding attribute stringifier support.
diff --git a/components/script/dom/webidls/Worker.webidl b/components/script/dom/webidls/Worker.webidl
index 9e5d2c36ad9..481c2d44849 100644
--- a/components/script/dom/webidls/Worker.webidl
+++ b/components/script/dom/webidls/Worker.webidl
@@ -6,7 +6,7 @@
// https://www.whatwg.org/html/#abstractworker
[NoInterfaceObject/*, Exposed=Window,Worker*/]
interface AbstractWorker {
- // attribute EventHandler onerror;
+ attribute EventHandler onerror;
};
// https://www.whatwg.org/html/#worker
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index 25b8d832fe4..4b614786efa 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -228,9 +228,16 @@ impl WebSocket {
}
impl WebSocketMethods for WebSocket {
+ // https://html.spec.whatwg.org/multipage/#handler-websocket-onopen
event_handler!(open, GetOnopen, SetOnopen);
+
+ // https://html.spec.whatwg.org/multipage/#handler-websocket-onclose
event_handler!(close, GetOnclose, SetOnclose);
+
+ // https://html.spec.whatwg.org/multipage/#handler-websocket-onerror
event_handler!(error, GetOnerror, SetOnerror);
+
+ // https://html.spec.whatwg.org/multipage/#handler-websocket-onmessage
event_handler!(message, GetOnmessage, SetOnmessage);
// https://html.spec.whatwg.org/multipage/#dom-websocket-url
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 8bce4247a4a..c463efa9f69 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -40,7 +40,6 @@ use timers::{IsInterval, TimerId, TimerManager, TimerCallback};
use webdriver_handlers::jsval_to_webdriver;
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
-use devtools_traits::{TracingMetadata};
use msg::compositor_msg::ScriptToCompositorMsg;
use msg::constellation_msg::{LoadData, PipelineId, SubpageId, ConstellationChan, WindowSizeData, WorkerId};
use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
@@ -504,8 +503,13 @@ impl WindowMethods for Window {
})
}
+ // https://html.spec.whatwg.org/multipage/#globaleventhandlers
global_event_handlers!();
+
+ // https://html.spec.whatwg.org/multipage/#handler-window-onunload
event_handler!(unload, GetOnunload, SetOnunload);
+
+ // https://html.spec.whatwg.org/multipage/#handler-onerror
error_event_handler!(error, GetOnerror, SetOnerror);
// https://developer.mozilla.org/en-US/docs/Web/API/Window/screen
@@ -681,10 +685,11 @@ impl Window {
debug!("script: performing reflow for goal {:?} reason {:?}", goal, reason);
- if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
- let marker = TimelineMarker::new("Reflow".to_owned(), TracingMetadata::IntervalStart);
- self.emit_timeline_marker(marker);
- }
+ let marker = if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
+ Some(TimelineMarker::start("Reflow".to_owned()))
+ } else {
+ None
+ };
// Layout will let us know when it's done.
let (join_chan, join_port) = channel();
@@ -725,9 +730,8 @@ impl Window {
self.pending_reflow_count.set(0);
- if self.need_emit_timeline_marker(TimelineMarkerType::Reflow) {
- let marker = TimelineMarker::new("Reflow".to_owned(), TracingMetadata::IntervalEnd);
- self.emit_timeline_marker(marker);
+ if let Some(marker) = marker {
+ self.emit_timeline_marker(marker.end());
}
}
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index 435de83ecff..2711e8502db 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -162,7 +162,11 @@ impl WorkerMethods for Worker {
Ok(())
}
+ // https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage
event_handler!(message, GetOnmessage, SetOnmessage);
+
+ // https://html.spec.whatwg.org/multipage/#handler-workerglobalscope-onerror
+ event_handler!(error, GetOnerror, SetOnerror);
}
pub struct WorkerMessageHandler {
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 1d7a097fd9e..5ab625c1d48 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -293,6 +293,7 @@ impl XMLHttpRequest {
}
impl XMLHttpRequestMethods for XMLHttpRequest {
+ // https://xhr.spec.whatwg.org/#handler-xhr-onreadystatechange
event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange);
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
@@ -959,7 +960,7 @@ impl XMLHttpRequest {
fn dispatch_response_progress_event(&self, type_: DOMString) {
let len = self.response.borrow().len() as u64;
- let total = self.response_headers.borrow().get::<ContentLength>().map(|x| {**x as u64});
+ let total = self.response_headers.borrow().get::<ContentLength>().map(|x| { **x as u64 });
self.dispatch_progress_event(false, type_, len, total);
}
fn set_timeout(&self, duration_ms: u32) {
diff --git a/components/script/dom/xmlhttprequesteventtarget.rs b/components/script/dom/xmlhttprequesteventtarget.rs
index 0e443d65041..627e4882dde 100644
--- a/components/script/dom/xmlhttprequesteventtarget.rs
+++ b/components/script/dom/xmlhttprequesteventtarget.rs
@@ -38,11 +38,24 @@ impl XMLHttpRequestEventTargetDerived for EventTarget {
}
impl XMLHttpRequestEventTargetMethods for XMLHttpRequestEventTarget {
+ // https://xhr.spec.whatwg.org/#handler-xhr-onloadstart
event_handler!(loadstart, GetOnloadstart, SetOnloadstart);
+
+ // https://xhr.spec.whatwg.org/#handler-xhr-onprogress
event_handler!(progress, GetOnprogress, SetOnprogress);
+
+ // https://xhr.spec.whatwg.org/#handler-xhr-onabort
event_handler!(abort, GetOnabort, SetOnabort);
+
+ // https://xhr.spec.whatwg.org/#handler-xhr-onerror
event_handler!(error, GetOnerror, SetOnerror);
+
+ // https://xhr.spec.whatwg.org/#handler-xhr-onload
event_handler!(load, GetOnload, SetOnload);
+
+ // https://xhr.spec.whatwg.org/#handler-xhr-ontimeout
event_handler!(timeout, GetOntimeout, SetOntimeout);
+
+ // https://xhr.spec.whatwg.org/#handler-xhr-onloadend
event_handler!(loadend, GetOnloadend, SetOnloadend);
}
diff --git a/components/script/lib.rs b/components/script/lib.rs
index bfe02d56cdc..ab2f0b94669 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -33,7 +33,7 @@
#![deny(unsafe_code)]
#![allow(non_snake_case)]
-#![doc="The script crate contains all matters DOM."]
+#![doc = "The script crate contains all matters DOM."]
#![plugin(string_cache_plugin)]
#![plugin(plugins)]
@@ -78,6 +78,7 @@ extern crate url;
extern crate uuid;
extern crate string_cache;
extern crate offscreen_gl_context;
+extern crate angle;
extern crate tendril;
pub mod cors;
@@ -102,7 +103,7 @@ mod webdriver_handlers;
use dom::bindings::codegen::RegisterBindings;
-#[cfg(target_os="linux")]
+#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
use std::mem;
@@ -118,7 +119,7 @@ fn perform_platform_specific_initialization() {
}
}
-#[cfg(not(target_os="linux"))]
+#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}
#[allow(unsafe_code)]
diff --git a/components/script/makefile.cargo b/components/script/makefile.cargo
index 9fc604382fc..fbc8533ee57 100644
--- a/components/script/makefile.cargo
+++ b/components/script/makefile.cargo
@@ -10,6 +10,8 @@ WEBIDLS = $(call rwildcard,$(WEBIDLS_SRC),*.webidl)
BINDINGS = $(patsubst %.webidl,%Binding.rs,$(WEBIDLS))
AUTOGEN_SRC = $(foreach var,$(BINDINGS),$(subst $(WEBIDLS_SRC),$(OUT_DIR)/Bindings,$(var)))
+export PYTHONPATH := $(BINDINGS_SRC)/parser:$(BINDINGS_SRC)/ply:$(PYTHONPATH)
+
CACHE_DIR = $(OUT_DIR)/_cache
bindinggen_dependencies := $(addprefix $(BINDINGS_SRC)/,BindingGen.py Bindings.conf Configuration.py CodegenRust.py parser/WebIDL.py) $(OUT_DIR)/ParserResults.pkl $(OUT_DIR)/Bindings/.done
@@ -28,18 +30,19 @@ $(CACHE_DIR)/.done:
touch $@
$(OUT_DIR)/ParserResults.pkl: $(globalgen_dependencies) $(WEBIDLS)
- $(PYTHON) -B $(BINDINGS_SRC)/pythonpath.py \
- -I$(BINDINGS_SRC)/parser -I$(BINDINGS_SRC)/ply \
- -D$(OUT_DIR) \
- $(BINDINGS_SRC)/GlobalGen.py $(BINDINGS_SRC)/Bindings.conf . \
- --cachedir=$(CACHE_DIR) \
- $(WEBIDLS)
+ $(PYTHON) \
+ $(BINDINGS_SRC)/GlobalGen.py \
+ --cachedir=$(CACHE_DIR) \
+ $(BINDINGS_SRC)/Bindings.conf \
+ $(OUT_DIR) \
+ . \
+ $(WEBIDLS)
$(AUTOGEN_SRC): $(OUT_DIR)/Bindings/%Binding.rs: $(bindinggen_dependencies) \
$(addprefix $(WEBIDLS_SRC)/,%.webidl)
- $(PYTHON) -B $(BINDINGS_SRC)/pythonpath.py \
- -I$(BINDINGS_SRC)/parser -I$(BINDINGS_SRC)/ply \
- -D$(OUT_DIR) \
+ $(PYTHON) \
$(BINDINGS_SRC)/BindingGen.py \
- $(BINDINGS_SRC)/Bindings.conf Bindings/$*Binding $(addprefix $(WEBIDLS_SRC)/,$*.webidl)
+ $(BINDINGS_SRC)/Bindings.conf \
+ $(OUT_DIR)/Bindings/$*Binding \
+ $(addprefix $(WEBIDLS_SRC)/,$*.webidl)
touch $@
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 5ae982bbee5..1ab86d67570 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -52,8 +52,8 @@ use timers::TimerId;
use webdriver_handlers;
use devtools_traits::{DevtoolsPageInfo, DevtoolScriptControlMsg};
-use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
-use devtools_traits::{TracingMetadata};
+use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker};
+use devtools_traits::{StartedTimelineMarker, TimelineMarkerType};
use msg::compositor_msg::{LayerId, ScriptToCompositorMsg};
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, FocusType};
@@ -2016,23 +2016,22 @@ impl Drop for ScriptTask {
}
struct AutoDOMEventMarker<'a> {
- script_task: &'a ScriptTask
+ script_task: &'a ScriptTask,
+ marker: Option<StartedTimelineMarker>,
}
impl<'a> AutoDOMEventMarker<'a> {
fn new(script_task: &'a ScriptTask) -> AutoDOMEventMarker<'a> {
- let marker = TimelineMarker::new("DOMEvent".to_owned(), TracingMetadata::IntervalStart);
- script_task.emit_timeline_marker(marker);
AutoDOMEventMarker {
- script_task: script_task
+ script_task: script_task,
+ marker: Some(TimelineMarker::start("DOMEvent".to_owned())),
}
}
}
impl<'a> Drop for AutoDOMEventMarker<'a> {
fn drop(&mut self) {
- let marker = TimelineMarker::new("DOMEvent".to_owned(), TracingMetadata::IntervalEnd);
- self.script_task.emit_timeline_marker(marker);
+ self.script_task.emit_timeline_marker(self.marker.take().unwrap().end());
}
}
diff --git a/components/script/textinput.rs b/components/script/textinput.rs
index 0f7164d5fa0..c647f63d4d8 100644
--- a/components/script/textinput.rs
+++ b/components/script/textinput.rs
@@ -78,12 +78,12 @@ pub enum Direction {
/// Was the keyboard event accompanied by the standard control modifier,
/// i.e. cmd on Mac OS or ctrl on other platforms.
-#[cfg(target_os="macos")]
+#[cfg(target_os = "macos")]
fn is_control_key(mods: KeyModifiers) -> bool {
mods.contains(SUPER) && !mods.contains(CONTROL | ALT)
}
-#[cfg(not(target_os="macos"))]
+#[cfg(not(target_os = "macos"))]
fn is_control_key(mods: KeyModifiers) -> bool {
mods.contains(CONTROL) && !mods.contains(SUPER | ALT)
}
diff --git a/components/script/timers.rs b/components/script/timers.rs
index f18b2231417..8fd712e7ac6 100644
--- a/components/script/timers.rs
+++ b/components/script/timers.rs
@@ -183,7 +183,7 @@ impl TimerManager {
if is_interval == IsInterval::NonInterval {
break;
}
- } else if id == control_handle.id() {;
+ } else if id == control_handle.id() {
match control_port.recv().unwrap() {
TimerControlMsg::Suspend => {
let msg = control_port.recv().unwrap();
@@ -194,7 +194,7 @@ impl TimerManager {
break;
},
}
- },
+ },
TimerControlMsg::Resume => panic!("Nothing to resume!"),
TimerControlMsg::Cancel => {
break;
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 77e83ecf130..af8c32f26b0 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -4,13 +4,18 @@ version = "0.0.1"
dependencies = [
"android_glue 0.0.2",
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "canvas 0.0.1",
+ "canvas_traits 0.0.1",
"compositing 0.0.1",
"devtools 0.0.1",
"devtools_traits 0.0.1",
"env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx 0.0.1",
"gfx_tests 0.0.1",
+ "gleam 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin_app 0.0.1",
+ "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"layout 0.0.1",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
@@ -22,6 +27,8 @@ dependencies = [
"profile_traits 0.0.1",
"script 0.0.1",
"script_tests 0.0.1",
+ "script_traits 0.0.1",
+ "style 0.0.1",
"style_tests 0.0.1",
"time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -57,6 +64,14 @@ version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "angle"
+version = "0.1.0"
+source = "git+https://github.com/ecoal95/angle?branch=servo#77288884bd7a89bf3019ca94dcda6c94cb178aa4"
+dependencies = [
+ "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "aster"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -161,7 +176,7 @@ dependencies = [
[[package]]
name = "clipboard"
version = "0.0.3"
-source = "git+https://github.com/aweinstock314/rust-clipboard#b0092c8630d4362e4618533822bea90a034b0792"
+source = "git+https://github.com/aweinstock314/rust-clipboard#8c4c31e73a5ac5afd97825acc4c534dccfc0ab9b"
dependencies = [
"clipboard-win 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -620,7 +635,7 @@ dependencies = [
[[package]]
name = "glutin"
version = "0.3.5"
-source = "git+https://github.com/servo/glutin?branch=servo#22a561c30a0560f445f50abcebf8439d264e0c67"
+source = "git+https://github.com/servo/glutin?branch=servo#0b055f889ce0baaa0fc186da4f3b5c31b7c6fd18"
dependencies = [
"android_glue 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1053,6 +1068,7 @@ name = "net_tests"
version = "0.0.1"
dependencies = [
"cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"net 0.0.1",
@@ -1349,6 +1365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "script"
version = "0.0.1"
dependencies = [
+ "angle 0.1.0 (git+https://github.com/ecoal95/angle?branch=servo)",
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas 0.0.1",
"canvas_traits 0.0.1",
diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml
index 00a30da7962..8d454044d4e 100644
--- a/components/servo/Cargo.toml
+++ b/components/servo/Cargo.toml
@@ -41,9 +41,10 @@ git = "https://github.com/servo/rust-png"
features = [ "serde-serialization" ]
[features]
-default = ["glutin_app", "window"]
+default = ["glutin_app", "window", "webdriver"]
window = ["glutin_app/window"]
headless = ["glutin_app/headless"]
+webdriver = ["webdriver_server"]
# Uncomment to profile on Linux:
#
@@ -77,17 +78,30 @@ path = "../util"
[dependencies.script]
path = "../script"
+[dependencies.script_traits]
+path = "../script_traits"
+
[dependencies.layout]
path = "../layout"
[dependencies.gfx]
path = "../gfx"
+[dependencies.style]
+path = "../style"
+
+[dependencies.canvas]
+path = "../canvas"
+
+[dependencies.canvas_traits]
+path = "../canvas_traits"
+
[dependencies.devtools]
path = "../devtools"
[dependencies.webdriver_server]
-path = "../webdriver_server"
+path = "../webdriver_server"
+optional = true
[dependencies.devtools_traits]
path = "../devtools_traits"
@@ -104,6 +118,15 @@ optional = true
version = "0.2"
features = [ "serde_serialization" ]
+[dependencies.euclid]
+version = "0.1"
+
+[dependencies.layers]
+git = "https://github.com/servo/rust-layers"
+
+[dependencies.gleam]
+version = "0.1"
+
[dependencies]
env_logger = "0.3"
time = "0.1.12"
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index dbf127803d3..8dd05d6f6f4 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -17,22 +17,67 @@
// The `Browser` is fed events from a generic type that implements the
// `WindowMethods` trait.
-extern crate compositing;
-extern crate devtools;
-extern crate devtools_traits;
-extern crate net;
-extern crate net_traits;
-extern crate msg;
-extern crate profile;
-extern crate profile_traits;
#[macro_use]
-extern crate util;
-extern crate script;
-extern crate layout;
-extern crate gfx;
+extern crate util as _util;
+
+mod export {
+ extern crate compositing;
+ extern crate devtools;
+ extern crate devtools_traits;
+ extern crate net;
+ extern crate net_traits;
+ extern crate msg;
+ extern crate profile;
+ extern crate profile_traits;
+ extern crate script;
+ extern crate script_traits;
+ extern crate layout;
+ extern crate gfx;
+ extern crate style;
+ extern crate canvas;
+ extern crate canvas_traits;
+
+ extern crate euclid;
+ extern crate url;
+ extern crate layers;
+ extern crate gleam;
+}
+
extern crate libc;
+
+#[cfg(feature = "webdriver")]
extern crate webdriver_server;
+#[cfg(feature = "webdriver")]
+fn webdriver(port: u16, constellation: msg::constellation_msg::ConstellationChan) {
+ webdriver_server::start_server(port, constellation.clone());
+}
+
+#[cfg(not(feature = "webdriver"))]
+fn webdriver(_port: u16, _constellation: msg::constellation_msg::ConstellationChan) { }
+
+pub use _util as util;
+pub use export::compositing;
+pub use export::devtools;
+pub use export::devtools_traits;
+pub use export::net;
+pub use export::net_traits;
+pub use export::msg;
+pub use export::profile;
+pub use export::profile_traits;
+pub use export::script;
+pub use export::script_traits;
+pub use export::layout;
+pub use export::gfx;
+pub use export::style;
+pub use export::canvas;
+pub use export::canvas_traits;
+
+pub use export::euclid;
+pub use export::url;
+pub use export::layers;
+pub use export::gleam::gl;
+
use compositing::CompositorEventListener;
use compositing::windowing::WindowEvent;
@@ -110,9 +155,11 @@ impl Browser {
devtools_chan,
supports_clipboard);
- if let Some(port) = opts.webdriver_port {
- webdriver_server::start_server(port, constellation_chan.clone());
- };
+ if cfg!(feature = "webdriver") {
+ if let Some(port) = opts.webdriver_port {
+ webdriver(port, constellation_chan.clone());
+ }
+ }
// The compositor coordinates with the client window to create the final
// rendered page and display it somewhere.
diff --git a/components/servo/main.rs b/components/servo/main.rs
index e96703026fe..afefe23f591 100644
--- a/components/servo/main.rs
+++ b/components/servo/main.rs
@@ -19,29 +19,23 @@
// The Servo engine
extern crate servo;
-// Window graphics compositing and message dispatch
-extern crate compositing;
-// Servo networking
-extern crate net;
-extern crate net_traits;
-// Servo common utilitiess
-extern crate util;
+
// The window backed by glutin
extern crate glutin_app as app;
extern crate time;
extern crate env_logger;
-#[cfg(target_os="android")]
+#[cfg(target_os = "android")]
#[macro_use]
extern crate android_glue;
-use compositing::windowing::WindowEvent;
-use net_traits::hosts;
use servo::Browser;
+use servo::compositing::windowing::WindowEvent;
+use servo::net_traits::hosts;
+use servo::util::opts;
use std::rc::Rc;
-use util::opts;
-#[cfg(target_os="android")]
+#[cfg(target_os = "android")]
use std::borrow::ToOwned;
fn main() {
@@ -134,16 +128,16 @@ impl app::NestedEventLoopListener for BrowserWrapper {
}
}
-#[cfg(target_os="android")]
+#[cfg(target_os = "android")]
fn setup_logging() {
android::setup_logging();
}
-#[cfg(not(target_os="android"))]
+#[cfg(not(target_os = "android"))]
fn setup_logging() {
}
-#[cfg(target_os="android")]
+#[cfg(target_os = "android")]
fn get_args() -> Vec<String> {
vec![
"servo".to_owned(),
@@ -151,7 +145,7 @@ fn get_args() -> Vec<String> {
]
}
-#[cfg(not(target_os="android"))]
+#[cfg(not(target_os = "android"))]
fn get_args() -> Vec<String> {
use std::env;
env::args().collect()
@@ -189,10 +183,10 @@ mod android {
use self::libc::funcs::c95::stdio::fgets;
use self::libc::funcs::posix88::stdio::fdopen;
use self::libc::funcs::posix88::unistd::{pipe, dup2};
+ use servo::util::task::spawn_named;
use std::ffi::CStr;
use std::ffi::CString;
use std::str::from_utf8;
- use util::task::spawn_named;
unsafe {
let mut pipes: [c_int; 2] = [ 0, 0 ];
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs
index c6a5296c739..089d45693c2 100644
--- a/components/style/properties.mako.rs
+++ b/components/style/properties.mako.rs
@@ -6585,6 +6585,9 @@ macro_rules! css_properties_accessors {
$macro_name! {
% for property in SHORTHANDS + LONGHANDS:
% if property.derived_from is None:
+ % if '-' in property.name:
+ [${property.ident.capitalize()}, Set${property.ident.capitalize()}, "${property.name}"],
+ % endif
% if property != LONGHANDS[-1]:
[${property.camel_case}, Set${property.camel_case}, "${property.name}"],
% else:
diff --git a/components/style/values.rs b/components/style/values.rs
index 7e5774d9262..2a5de980ed9 100644
--- a/components/style/values.rs
+++ b/components/style/values.rs
@@ -151,6 +151,7 @@ pub mod specified {
pub enum FontRelativeLength {
Em(CSSFloat),
Ex(CSSFloat),
+ Ch(CSSFloat),
Rem(CSSFloat)
}
@@ -159,6 +160,7 @@ pub mod specified {
match self {
&FontRelativeLength::Em(length) => write!(dest, "{}em", length),
&FontRelativeLength::Ex(length) => write!(dest, "{}ex", length),
+ &FontRelativeLength::Ch(length) => write!(dest, "{}ch", length),
&FontRelativeLength::Rem(length) => write!(dest, "{}rem", length)
}
}
@@ -172,9 +174,10 @@ pub mod specified {
{
match self {
&FontRelativeLength::Em(length) => reference_font_size.scale_by(length),
- &FontRelativeLength::Ex(length) => {
- let x_height = 0.5; // TODO: find that from the font
- reference_font_size.scale_by(length * x_height)
+ &FontRelativeLength::Ex(length) | &FontRelativeLength::Ch(length) => {
+ // https://github.com/servo/servo/issues/7462
+ let em_factor = 0.5;
+ reference_font_size.scale_by(length * em_factor)
},
&FontRelativeLength::Rem(length) => root_font_size.scale_by(length)
}
@@ -284,6 +287,7 @@ pub mod specified {
match self {
FontRelativeLength::Em(v) => FontRelativeLength::Em(v * scalar),
FontRelativeLength::Ex(v) => FontRelativeLength::Ex(v * scalar),
+ FontRelativeLength::Ch(v) => FontRelativeLength::Ch(v * scalar),
FontRelativeLength::Rem(v) => FontRelativeLength::Rem(v * scalar),
}
}
@@ -338,6 +342,7 @@ pub mod specified {
// font-relative
"em" => Ok(Length::FontRelative(FontRelativeLength::Em(value))),
"ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))),
+ "ch" => Ok(Length::FontRelative(FontRelativeLength::Ch(value))),
"rem" => Ok(Length::FontRelative(FontRelativeLength::Rem(value))),
// viewport percentages
"vw" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vw(value))),
diff --git a/components/util/opts.rs b/components/util/opts.rs
index 10a2bd84a78..8a8459f687c 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -56,8 +56,6 @@ pub struct Opts {
pub nonincremental_layout: bool,
- pub nossl: bool,
-
/// Where to load userscripts from, if any. An empty string will load from
/// the resources/user-agent-js directory, and if the option isn't passed userscripts
/// won't be loaded
@@ -335,10 +333,10 @@ fn args_fail(msg: &str) -> ! {
// Always use CPU painting on android.
-#[cfg(target_os="android")]
+#[cfg(target_os = "android")]
static FORCE_CPU_PAINTING: bool = true;
-#[cfg(not(target_os="android"))]
+#[cfg(not(target_os = "android"))]
static FORCE_CPU_PAINTING: bool = false;
enum UserAgent {
@@ -361,15 +359,15 @@ fn default_user_agent_string(agent: UserAgent) -> String {
}.to_owned()
}
-#[cfg(target_os="android")]
+#[cfg(target_os = "android")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android;
// FIXME: This requires https://github.com/servo/servo/issues/7138 to provide the
// correct string in Gonk builds (i.e., it will never be chosen today).
-#[cfg(target_os="gonk")]
+#[cfg(target_os = "gonk")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Gonk;
-#[cfg(not(any(target_os="android", target_os="gonk")))]
+#[cfg(not(any(target_os = "android", target_os = "gonk")))]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop;
pub fn default_opts() -> Opts {
@@ -383,7 +381,6 @@ pub fn default_opts() -> Opts {
mem_profiler_period: None,
layout_threads: 1,
nonincremental_layout: false,
- nossl: false,
userscripts: None,
user_stylesheets: Vec::new(),
output_file: None,
@@ -532,7 +529,6 @@ pub fn from_cmdline_args(args: &[String]) {
};
let nonincremental_layout = opt_match.opt_present("i");
- let nossl = opt_match.opt_present("no-ssl");
let mut bubble_inline_sizes_separately = debug_options.bubble_widths;
if debug_options.trace_layout {
@@ -588,7 +584,6 @@ pub fn from_cmdline_args(args: &[String]) {
mem_profiler_period: mem_profiler_period,
layout_threads: layout_threads,
nonincremental_layout: nonincremental_layout,
- nossl: nossl,
userscripts: opt_match.opt_default("userscripts", ""),
user_stylesheets: user_stylesheets,
output_file: opt_match.opt_str("o"),
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index 78284ce5378..a2365e9a784 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -56,6 +56,14 @@ version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "angle"
+version = "0.1.0"
+source = "git+https://github.com/ecoal95/angle?branch=servo#77288884bd7a89bf3019ca94dcda6c94cb178aa4"
+dependencies = [
+ "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "aster"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -160,7 +168,7 @@ dependencies = [
[[package]]
name = "clipboard"
version = "0.0.3"
-source = "git+https://github.com/aweinstock314/rust-clipboard#b0092c8630d4362e4618533822bea90a034b0792"
+source = "git+https://github.com/aweinstock314/rust-clipboard#8c4c31e73a5ac5afd97825acc4c534dccfc0ab9b"
dependencies = [
"clipboard-win 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -612,7 +620,7 @@ dependencies = [
[[package]]
name = "glutin"
version = "0.3.5"
-source = "git+https://github.com/servo/glutin?branch=servo#22a561c30a0560f445f50abcebf8439d264e0c67"
+source = "git+https://github.com/servo/glutin?branch=servo#0b055f889ce0baaa0fc186da4f3b5c31b7c6fd18"
dependencies = [
"android_glue 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1327,6 +1335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "script"
version = "0.0.1"
dependencies = [
+ "angle 0.1.0 (git+https://github.com/ecoal95/angle?branch=servo)",
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas 0.0.1",
"canvas_traits 0.0.1",
diff --git a/ports/glutin/lib.rs b/ports/glutin/lib.rs
index 0bd7fffff8e..cb611153be0 100644
--- a/ports/glutin/lib.rs
+++ b/ports/glutin/lib.rs
@@ -7,7 +7,7 @@
#![feature(box_syntax, result_expect)]
#[macro_use] extern crate bitflags;
-#[cfg(target_os="macos")] extern crate cgl;
+#[cfg(target_os = "macos")] extern crate cgl;
extern crate compositing;
extern crate euclid;
extern crate gleam;
@@ -19,9 +19,9 @@ extern crate net_traits;
#[cfg(feature = "window")] extern crate script_traits;
extern crate time;
extern crate util;
-#[cfg(target_os="android")] extern crate egl;
+#[cfg(target_os = "android")] extern crate egl;
extern crate url;
-#[cfg(target_os="linux")] extern crate x11;
+#[cfg(target_os = "linux")] extern crate x11;
use compositing::windowing::WindowEvent;
use euclid::scale_factor::ScaleFactor;
diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs
index a01987ee1f7..ec96727d811 100644
--- a/ports/glutin/window.rs
+++ b/ports/glutin/window.rs
@@ -35,7 +35,7 @@ use std::cell::{Cell, RefCell};
#[cfg(feature = "window")]
use util::opts;
-#[cfg(all(feature = "headless", target_os="linux"))]
+#[cfg(all(feature = "headless", target_os = "linux"))]
use std::ptr;
#[cfg(feature = "window")]
@@ -56,15 +56,15 @@ bitflags! {
}
// Some shortcuts use Cmd on Mac and Control on other systems.
-#[cfg(all(feature = "window", target_os="macos"))]
+#[cfg(all(feature = "window", target_os = "macos"))]
const CMD_OR_CONTROL: constellation_msg::KeyModifiers = SUPER;
-#[cfg(all(feature = "window", not(target_os="macos")))]
+#[cfg(all(feature = "window", not(target_os = "macos")))]
const CMD_OR_CONTROL: constellation_msg::KeyModifiers = CONTROL;
// Some shortcuts use Cmd on Mac and Alt on other systems.
-#[cfg(all(feature = "window", target_os="macos"))]
+#[cfg(all(feature = "window", target_os = "macos"))]
const CMD_OR_ALT: constellation_msg::KeyModifiers = SUPER;
-#[cfg(all(feature = "window", not(target_os="macos")))]
+#[cfg(all(feature = "window", not(target_os = "macos")))]
const CMD_OR_ALT: constellation_msg::KeyModifiers = ALT;
// This should vary by zoom level and maybe actual text size (focused or under cursor)
@@ -138,22 +138,22 @@ impl Window {
}
}
- #[cfg(not(target_os="android"))]
+ #[cfg(not(target_os = "android"))]
fn gl_version() -> GlRequest {
GlRequest::Specific(Api::OpenGl, (3, 0))
}
- #[cfg(target_os="android")]
+ #[cfg(target_os = "android")]
fn gl_version() -> GlRequest {
GlRequest::Specific(Api::OpenGlEs, (2, 0))
}
- #[cfg(not(target_os="android"))]
+ #[cfg(not(target_os = "android"))]
fn load_gl_functions(window: &glutin::Window) {
gl::load_with(|s| window.get_proc_address(s));
}
- #[cfg(target_os="android")]
+ #[cfg(target_os = "android")]
fn load_gl_functions(_: &glutin::Window) {
}
@@ -290,7 +290,7 @@ impl Window {
self.event_queue.borrow_mut().push(WindowEvent::MouseWindowEventClass(event));
}
- #[cfg(target_os="macos")]
+ #[cfg(target_os = "macos")]
fn handle_next_event(&self) -> bool {
let event = self.window.wait_events().next().unwrap();
let mut close = self.handle_window_event(event);
@@ -305,7 +305,7 @@ impl Window {
close
}
- #[cfg(any(target_os="linux", target_os="android"))]
+ #[cfg(any(target_os = "linux", target_os = "android"))]
fn handle_next_event(&self) -> bool {
use std::thread::sleep_ms;
@@ -478,7 +478,7 @@ impl Window {
result
}
- #[cfg(all(feature = "window", not(target_os="win")))]
+ #[cfg(all(feature = "window", not(target_os = "win")))]
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) {
match (mods, key) {
(CMD_OR_CONTROL, Key::LeftBracket) => {
@@ -491,19 +491,19 @@ impl Window {
}
}
- #[cfg(all(feature = "window", target_os="win"))]
+ #[cfg(all(feature = "window", target_os = "win"))]
fn platform_handle_key(&self, key: Key, mods: constellation_msg::KeyModifiers) {
}
}
// WindowProxy is not implemented for android yet
-#[cfg(all(feature = "window", target_os="android"))]
+#[cfg(all(feature = "window", target_os = "android"))]
fn create_window_proxy(_: &Rc<Window>) -> Option<glutin::WindowProxy> {
None
}
-#[cfg(all(feature = "window", not(target_os="android")))]
+#[cfg(all(feature = "window", not(target_os = "android")))]
fn create_window_proxy(window: &Rc<Window>) -> Option<glutin::WindowProxy> {
Some(window.window.create_window_proxy())
}
@@ -623,7 +623,7 @@ impl WindowMethods for Window {
true
}
- #[cfg(target_os="linux")]
+ #[cfg(target_os = "linux")]
fn native_display(&self) -> NativeDisplay {
use x11::xlib;
unsafe {
@@ -631,7 +631,7 @@ impl WindowMethods for Window {
}
}
- #[cfg(not(target_os="linux"))]
+ #[cfg(not(target_os = "linux"))]
fn native_display(&self) -> NativeDisplay {
NativeDisplay::new()
}
@@ -791,7 +791,7 @@ impl WindowMethods for Window {
true
}
- #[cfg(target_os="linux")]
+ #[cfg(target_os = "linux")]
fn native_display(&self) -> NativeDisplay {
NativeDisplay::new(ptr::null_mut())
}
diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock
index df88f068672..0f810c0de64 100644
--- a/ports/gonk/Cargo.lock
+++ b/ports/gonk/Cargo.lock
@@ -42,6 +42,14 @@ dependencies = [
]
[[package]]
+name = "angle"
+version = "0.1.0"
+source = "git+https://github.com/ecoal95/angle?branch=servo#77288884bd7a89bf3019ca94dcda6c94cb178aa4"
+dependencies = [
+ "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "aster"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -141,7 +149,7 @@ dependencies = [
[[package]]
name = "clipboard"
version = "0.0.3"
-source = "git+https://github.com/aweinstock314/rust-clipboard#b0092c8630d4362e4618533822bea90a034b0792"
+source = "git+https://github.com/aweinstock314/rust-clipboard#8c4c31e73a5ac5afd97825acc4c534dccfc0ab9b"
dependencies = [
"clipboard-win 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1193,6 +1201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "script"
version = "0.0.1"
dependencies = [
+ "angle 0.1.0 (git+https://github.com/ecoal95/angle?branch=servo)",
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas 0.0.1",
"canvas_traits 0.0.1",
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index d49632882e5..73d9b9046fa 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -242,9 +242,6 @@ class MachCommands(CommandBase):
notify_build_done(elapsed)
print("Build completed in %0.2fs" % elapsed)
- # XXX(#7339) Android build is broken
- if android:
- return 0
return status
@Command('build-cef',
diff --git a/python/tidy.py b/python/tidy.py
index 110b0e9a01c..e576d501a37 100644
--- a/python/tidy.py
+++ b/python/tidy.py
@@ -228,33 +228,35 @@ def check_rust(file_name, contents):
line = merged_lines + line
merged_lines = ''
- # get rid of strings and chars because cases like regex expression
- line = re.sub('".*?"|\'.*?\'', '', line)
+ # get rid of strings and chars because cases like regex expression, keep attributes
+ if not line_is_attribute(line):
+ line = re.sub('".*?"|\'.*?\'', '', line)
- # get rid of comments and attributes
- line = re.sub('//.*?$|/\*.*?$|^\*.*?$|^#.*?$', '', line)
+ # get rid of comments
+ line = re.sub('//.*?$|/\*.*?$|^\*.*?$', '', line)
+
+ # get rid of attributes that do not contain =
+ line = re.sub('^#[A-Za-z0-9\(\)\[\]_]*?$', '', line)
match = re.search(r",[A-Za-z0-9]", line)
if match:
yield (idx + 1, "missing space after ,")
- # Avoid flagging <Item=Foo> constructs
- def is_associated_type(match, line, index):
- open_angle = line[0:match.end()].rfind('<')
- close_angle = line[open_angle:].find('>') if open_angle != -1 else -1
- is_equals = match.group(0)[index] == '='
- generic_open = open_angle != -1 and open_angle < match.start()
- generic_close = close_angle != -1 and close_angle + open_angle >= match.end()
- return is_equals and generic_open and generic_close
-
- # - not included because of scientific notation (1e-6)
- match = re.search(r"[A-Za-z0-9][\+/\*%=]", line)
+ if line_is_attribute(line):
+ pre_space_re = r"[A-Za-z0-9]="
+ post_space_re = r"=[A-Za-z0-9\"]"
+ else:
+ # - not included because of scientific notation (1e-6)
+ pre_space_re = r"[A-Za-z0-9][\+/\*%=]"
+ # * not included because of dereferencing and casting
+ # - not included because of unary negation
+ post_space_re = r"[\+/\%=][A-Za-z0-9\"]"
+
+ match = re.search(pre_space_re, line)
if match and not is_associated_type(match, line, 1):
yield (idx + 1, "missing space before %s" % match.group(0)[1])
- # * not included because of dereferencing and casting
- # - not included because of unary negation
- match = re.search(r"[\+/\%=][A-Za-z0-9]", line)
+ match = re.search(post_space_re, line)
if match and not is_associated_type(match, line, 0):
yield (idx + 1, "missing space after %s" % match.group(0)[0])
@@ -283,6 +285,16 @@ def check_rust(file_name, contents):
if match:
yield (idx + 1, "missing space before {")
+ # ignored cases like {} and }}
+ match = re.search(r"[^\s{}]}", line)
+ if match and not (line.startswith("use") or line.startswith("pub use")):
+ yield (idx + 1, "missing space before }")
+
+ # ignored cases like {} and {{
+ match = re.search(r"{[^\s{}]", line)
+ if match and not (line.startswith("use") or line.startswith("pub use")):
+ yield (idx + 1, "missing space after {")
+
# imports must be in the same line and alphabetically sorted
if line.startswith("use "):
use = line[4:]
@@ -300,6 +312,20 @@ def check_rust(file_name, contents):
uses = []
+# Avoid flagging <Item=Foo> constructs
+def is_associated_type(match, line, index):
+ open_angle = line[0:match.end()].rfind('<')
+ close_angle = line[open_angle:].find('>') if open_angle != -1 else -1
+ is_equals = match.group(0)[index] == '='
+ generic_open = open_angle != -1 and open_angle < match.start()
+ generic_close = close_angle != -1 and close_angle + open_angle >= match.end()
+ return is_equals and generic_open and generic_close
+
+
+def line_is_attribute(line):
+ return re.search(r"#\[.*\]", line)
+
+
def check_webidl_spec(file_name, contents):
# Sorted by this function (in pseudo-Rust). The idea is to group the same
# organization together.
@@ -353,7 +379,17 @@ def check_spec(file_name, contents):
raise StopIteration
file_name = os.path.relpath(os.path.splitext(file_name)[0], base_path)
patt = re.compile("^\s*\/\/.+")
- pattern = "impl<'a> %sMethods for &'a %s {" % (file_name, file_name)
+
+ # Pattern representing a line with a macro
+ macro_patt = re.compile("^\s*\S+!(.*)$")
+
+ # Pattern representing a line with comment containing a spec link
+ link_patt = re.compile("^\s*///? https://.+$")
+
+ # Pattern representing a line with comment
+ comment_patt = re.compile("^\s*///?.+$")
+
+ pattern = "impl %sMethods for %s {" % (file_name, file_name)
contents = contents.splitlines(True)
brace_count = 0
in_impl = False
@@ -363,9 +399,16 @@ def check_spec(file_name, contents):
if not patt.match(line):
if pattern.lower() in line.lower():
in_impl = True
- if "fn " in line and brace_count == 1:
- if "// https://" not in contents[idx - 1] and "// https://" not in contents[idx - 2]:
- yield (idx + 1, "method declared in webidl is missing a comment with a specification link")
+ if ("fn " in line or macro_patt.match(line)) and brace_count == 1:
+ for up_idx in range(1, idx + 1):
+ up_line = contents[idx - up_idx]
+ if link_patt.match(up_line):
+ # Comment with spec link exists
+ break
+ if not comment_patt.match(up_line):
+ # No more comments exist above, yield warning
+ yield (idx + 1, "method declared in webidl is missing a comment with a specification link")
+ break
if '{' in line and in_impl:
brace_count += 1
if '}' in line and in_impl:
diff --git a/tests/ref/absolute_table.html b/tests/ref/absolute_table.html
new file mode 100644
index 00000000000..b0dc978e34f
--- /dev/null
+++ b/tests/ref/absolute_table.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<style>
+div { display:table;position:absolute;top:0px;right:40px }
+</style>
+<div>
+XXX
+</div>
diff --git a/tests/ref/absolute_table_ref.html b/tests/ref/absolute_table_ref.html
new file mode 100644
index 00000000000..40018562574
--- /dev/null
+++ b/tests/ref/absolute_table_ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<style>
+div { display:block;position:absolute;top:0px;right:40px }
+</style>
+<div>
+XXX
+</div>
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index ed4e0d91a4b..59d0934faae 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -12,6 +12,7 @@ fragment=top != ../html/acid2.html acid2_ref.html
== abs_rel_explicit_height.html abs_rel_explicit_height_ref.html
== absolute_hypothetical_with_intervening_inline_block_a.html absolute_hypothetical_with_intervening_inline_block_ref.html
== absolute_inline_containing_block_a.html absolute_inline_containing_block_ref.html
+== absolute_table.html absolute_table_ref.html
== absolute_z_index_auto_paint_order_a.html absolute_z_index_auto_paint_order_ref.html
== acid1_a.html acid1_b.html
== acid2_noscroll.html acid2_ref_broken.html
@@ -61,6 +62,7 @@ flaky_cpu == append_style_a.html append_style_b.html
== border_code_tag.html border_code_tag_ref.html
== border_collapse_missing_cell_a.html border_collapse_missing_cell_ref.html
== border_collapse_simple_a.html border_collapse_simple_ref.html
+== border_radius_asymmetric_sizes_a.html border_radius_asymmetric_sizes_ref.html
== border_radius_clip_a.html border_radius_clip_ref.html
!= border_radius_dashed_a.html border_radius_dashed_ref.html
== border_radius_overlapping_a.html border_radius_overlapping_ref.html
@@ -294,6 +296,7 @@ flaky_cpu == linebreak_simple_a.html linebreak_simple_b.html
== position_relative_painting_order_a.html position_relative_painting_order_ref.html
== position_relative_stacking_context_a.html position_relative_stacking_context_ref.html
== position_relative_top_percentage_a.html position_relative_top_percentage_b.html
+== position_relative_vertical_percentage_overflow_a.html position_relative_vertical_percentage_overflow_ref.html
== pre_ignorable_whitespace_a.html pre_ignorable_whitespace_ref.html
== pre_with_tab.html pre_with_tab_ref.html
== pseudo_element_a.html pseudo_element_b.html
diff --git a/tests/ref/border_radius_asymmetric_sizes_a.html b/tests/ref/border_radius_asymmetric_sizes_a.html
new file mode 100644
index 00000000000..94676b11941
--- /dev/null
+++ b/tests/ref/border_radius_asymmetric_sizes_a.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+ <meta content="utf-8" http-equiv="encoding">
+ <style type="text/css">
+ div.box {
+ background: white;
+ border-width: 10px 10px 10px 10px;
+ border-color: yellow red green blue;
+ border-radius: 10px;
+ border-style: solid;
+ height: 190px;
+ width: 190px;
+ }
+ div.top {
+ border-top-width: 30px;
+ }
+ div.right {
+ border-right-width: 30px;
+ }
+ div.bottom {
+ border-bottom-width: 30px;
+ }
+ div.left {
+ border-left-width: 30px;
+ }
+ div.radius10px {
+ border-radius: 10px;
+ }
+ div.radius20px {
+ border-radius: 20px;
+ }
+ div.radius30px {
+ border-radius: 30px;
+ }
+ div.radius40px {
+ border-radius: 40px;
+ }
+
+ #box2, #box4, #box6, #box8, #box10, #box12, #box14 {
+ width: 170px;
+ }
+ </style>
+ </head>
+ <body>
+ <h2>Border Radius - 10px</h2>
+ Box#1<div id="box1" class="box top"></div><br>
+ Box#2<div id="box2" class="box right"></div><br>
+ Box#3<div id="box3" class="box bottom"></div><br>
+ Box#4<div id="box4" class="box left"></div><br>
+
+ <h2>Border Radius - 20px</h2>
+ Box#5<div id="box5" class="box top radius20px"></div><br>
+ Box#6<div id="box6" class="box right radius20px"></div><br>
+ Box#7<div id="box7" class="box bottom radius20px"></div><br>
+ Box#8<div id="box8" class="box left radius20px"></div><br>
+
+ <h2>Border Radius - 30px</h2>
+ Box#9<div id="box9" class="box top radius30px"></div><br>
+ Box#10<div id="box10" class="box right radius30px"></div><br>
+ Box#11<div id="box11" class="box bottom radius30px"></div><br>
+ Box#12<div id="box12" class="box left radius30px"></div><br>
+
+ <h2>Border Radius - 40px</h2>
+ Box#13<div id="box13" class="box top radius40px"></div><br>
+ Box#14<div id="box14" class="box right radius40px"></div><br>
+ Box#15<div id="box15" class="box bottom radius40px"></div><br>
+ Box#16<div id="box16" class="box left radius40px"></div><br>
+ </body>
+</html>
diff --git a/tests/ref/border_radius_asymmetric_sizes_ref.html b/tests/ref/border_radius_asymmetric_sizes_ref.html
new file mode 100644
index 00000000000..4993ae6fd7d
--- /dev/null
+++ b/tests/ref/border_radius_asymmetric_sizes_ref.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+ <meta content="utf-8" http-equiv="encoding">
+ <style type="text/css">
+ .box-top {
+ background: white;
+ width: 190px;
+ height: 0px;
+ margin: 0px;
+ border-style: solid;
+ border-color: yellow red green blue;
+ }
+ .box-middle {
+ background: white;
+ width: 190px;
+ height: 190px;
+ margin: 0px;
+ border-style: solid;
+ border-color: yellow red green blue;
+ }
+ .box-bottom {
+ background: white;
+ width: 190px;
+ height: 0px;
+ margin: 0px;
+ border-style: solid;
+ border-color: yellow red green blue;
+ }
+ .top-radius-10 {
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ }
+ .bottom-radius-10 {
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
+ }
+ .top-radius-20 {
+ border-top-left-radius: 20px;
+ border-top-right-radius: 20px;
+ }
+ .bottom-radius-20 {
+ border-bottom-left-radius: 20px;
+ border-bottom-right-radius: 20px;
+ }
+ .top-radius-30 {
+ border-top-left-radius: 30px;
+ border-top-right-radius: 30px;
+ }
+ .bottom-radius-30 {
+ border-bottom-left-radius: 30px;
+ border-bottom-right-radius: 30px;
+ }
+ .top-radius-40 {
+ border-top-left-radius: 40px;
+ border-top-right-radius: 40px;
+ }
+ .bottom-radius-40 {
+ border-bottom-left-radius: 40px;
+ border-bottom-right-radius: 40px;
+ }
+ .box1-top {
+ border-top-width: 30px;
+ border-right-width: 10px;
+ border-bottom-width: 0px;
+ border-left-width: 10px;
+ }
+ .box1-middle {
+ border-width: 0px 10px 0px 10px;
+ }
+ .box1-bottom {
+ border-width: 0px 10px 10px 10px;
+ }
+ .box2-top {
+ width: 170px;
+ border-width: 10px 30px 0px 10px;
+ }
+ .box2-middle {
+ width: 170px;
+ border-width: 0px 30px 0px 10px;
+ }
+ .box2-bottom {
+ width: 170px;
+ border-width: 0px 30px 10px 10px;
+ }
+ .box3-top {
+ border-width: 10px 10px 0px 10px;
+ }
+ .box3-middle {
+ border-width: 0px 10px 0px 10px;
+ }
+ .box3-bottom {
+ border-top-width: 0px;
+ border-left-width: 10px;
+ border-right-width: 10px;
+ border-bottom-width: 30px;
+ }
+ .box4-top {
+ width: 170px;
+ border-width: 10px 10px 0px 30px;
+ }
+ .box4-middle {
+ width: 170px;
+ border-width: 0px 10px 0px 30px;
+ }
+ .box4-bottom {
+ width: 170px;
+ border-top-width: 0px;
+ border-left-width: 30px;
+ border-right-width: 10px;
+ border-bottom-width: 10px;
+ }
+ </style>
+ </head>
+ <body>
+ <h2>Border Radius - 10px</h2>
+ Box#1
+ <div id="box1-top" class="box-top box1-top top-radius-10"></div>
+ <div id="box1-middle" class="box-middle box1-middle middle-radius-10"></div>
+ <div id="box1-bottom" class="box-bottom box1-bottom bottom-radius-10"></div>
+ <br>
+
+ Box#2
+ <div id="box2-top" class="box-top box2-top top-radius-10"></div>
+ <div id="box2-middle" class="box-middle box2-middle middle-radius-10"></div>
+ <div id="box2-bottom" class="box-bottom box2-bottom bottom-radius-10"></div>
+ <br>
+
+ Box#3
+ <div id="box3-top" class="box-top box3-top top-radius-10"></div>
+ <div id="box3-middle" class="box-middle box3-middle middle-radius-10"></div>
+ <div id="box3-bottom" class="box-bottom box3-bottom bottom-radius-10"></div>
+ <br>
+
+ Box#4
+ <div id="box4-top" class="box-top box4-top top-radius-10"></div>
+ <div id="box4-middle" class="box-middle box4-middle middle-radius-10"></div>
+ <div id="box4-bottom" class="box-bottom box4-bottom bottom-radius-10"></div>
+ <br>
+
+ <h2>Border Radius - 20px</h2>
+ Box#5
+ <div id="box5-top" class="box-top box1-top top-radius-20"></div>
+ <div id="box5-middle" class="box-middle box1-middle middle-radius-20"></div>
+ <div id="box5-bottom" class="box-bottom box1-bottom bottom-radius-20"></div>
+ <br>
+
+ Box#6
+ <div id="box6-top" class="box-top box2-top top-radius-20"></div>
+ <div id="box6-middle" class="box-middle box2-middle middle-radius-20"></div>
+ <div id="box6-bottom" class="box-bottom box2-bottom bottom-radius-20"></div>
+ <br>
+
+ Box#7
+ <div id="box7-top" class="box-top box3-top top-radius-20"></div>
+ <div id="box7-middle" class="box-middle box3-middle middle-radius-20"></div>
+ <div id="box7-bottom" class="box-bottom box3-bottom bottom-radius-20"></div>
+ <br>
+
+ Box#8
+ <div id="box8-top" class="box-top box4-top top-radius-20"></div>
+ <div id="box8-middle" class="box-middle box4-middle middle-radius-20"></div>
+ <div id="box8-bottom" class="box-bottom box4-bottom bottom-radius-20"></div>
+ <br>
+
+ <h2>Border Radius - 30px</h2>
+ Box#9
+ <div id="box9-top" class="box-top box1-top top-radius-30"></div>
+ <div id="box9-middle" class="box-middle box1-middle middle-radius-30"></div>
+ <div id="box9-bottom" class="box-bottom box1-bottom bottom-radius-30"></div>
+ <br>
+
+ Box#10
+ <div id="box10-top" class="box-top box2-top top-radius-30"></div>
+ <div id="box10-middle" class="box-middle box2-middle middle-radius-30"></div>
+ <div id="box10-bottom" class="box-bottom box2-bottom bottom-radius-30"></div>
+ <br>
+
+ Box#11
+ <div id="box11-top" class="box-top box3-top top-radius-30"></div>
+ <div id="box11-middle" class="box-middle box3-middle middle-radius-30"></div>
+ <div id="box11-bottom" class="box-bottom box3-bottom bottom-radius-30"></div>
+ <br>
+
+ Box#12
+ <div id="box12-top" class="box-top box4-top top-radius-30"></div>
+ <div id="box12-middle" class="box-middle box4-middle middle-radius-30"></div>
+ <div id="box12-bottom" class="box-bottom box4-bottom bottom-radius-30"></div>
+ <br>
+
+ <h2>Border Radius - 40px</h2>
+ Box#13
+ <div id="box13-top" class="box-top box1-top top-radius-40"></div>
+ <div id="box13-middle" class="box-middle box1-middle middle-radius-40"></div>
+ <div id="box13-bottom" class="box-bottom box1-bottom bottom-radius-40"></div>
+ <br>
+
+ Box#14
+ <div id="box14-top" class="box-top box2-top top-radius-40"></div>
+ <div id="box14-middle" class="box-middle box2-middle middle-radius-40"></div>
+ <div id="box14-bottom" class="box-bottom box2-bottom bottom-radius-40"></div>
+ <br>
+
+ Box#15
+ <div id="box15-top" class="box-top box3-top top-radius-40"></div>
+ <div id="box15-middle" class="box-middle box3-middle middle-radius-40"></div>
+ <div id="box15-bottom" class="box-bottom box3-bottom bottom-radius-40"></div>
+ <br>
+
+ Box#16
+ <div id="box16-top" class="box-top box4-top top-radius-40"></div>
+ <div id="box16-middle" class="box-middle box4-middle middle-radius-40"></div>
+ <div id="box16-bottom" class="box-bottom box4-bottom bottom-radius-40"></div>
+ <br>
+ </body>
+</html>
diff --git a/tests/ref/position_relative_vertical_percentage_overflow_a.html b/tests/ref/position_relative_vertical_percentage_overflow_a.html
new file mode 100644
index 00000000000..ca9aae49050
--- /dev/null
+++ b/tests/ref/position_relative_vertical_percentage_overflow_a.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<style>
+body, html {
+ margin: 0;
+}
+#a {
+ display: block;
+ position: absolute;
+ top: 100px;
+ left: 100px;
+ width: 100px;
+ height: 100px;
+ transform: translateX(0px); /* force creation of stacking context */
+}
+#b {
+ display: block;
+ position: relative;
+ top: -50%;
+ width: 100px;
+ height: 100px;
+ background: purple;
+}
+</style>
+<div id=a><div id=b>
+
diff --git a/tests/ref/position_relative_vertical_percentage_overflow_ref.html b/tests/ref/position_relative_vertical_percentage_overflow_ref.html
new file mode 100644
index 00000000000..32bdcb8ab59
--- /dev/null
+++ b/tests/ref/position_relative_vertical_percentage_overflow_ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+body, html {
+ margin: 0;
+}
+#a {
+ display: block;
+ position: absolute;
+ top: 50px;
+ left: 100px;
+ width: 100px;
+ height: 100px;
+ background: purple;
+}
+</style>
+<div id=a>
+
diff --git a/tests/ref/webgl-context/tex_image_2d_simple.html b/tests/ref/webgl-context/tex_image_2d_simple.html
index 9ba19e2e6dc..60ea4674530 100644
--- a/tests/ref/webgl-context/tex_image_2d_simple.html
+++ b/tests/ref/webgl-context/tex_image_2d_simple.html
@@ -10,6 +10,7 @@
</style>
<canvas id="c" width="256" height="256"></canvas>
<script id="vertex_shader" type="x-shader/x-vertex">
+ precision mediump float;
attribute vec2 a_texCoord;
attribute vec2 a_position;
varying vec2 v_texCoord;
@@ -21,6 +22,7 @@
</script>
<script id="fragment_shader" type="x-shader/x-fragment">
+ precision mediump float;
uniform sampler2D u_image;
varying vec2 v_texCoord;
void main() {
diff --git a/tests/unit/net/Cargo.toml b/tests/unit/net/Cargo.toml
index 62c72b975bc..fdd82f7fb6d 100644
--- a/tests/unit/net/Cargo.toml
+++ b/tests/unit/net/Cargo.toml
@@ -25,3 +25,4 @@ cookie = "0.1"
hyper = "0.6"
url = "0.2"
time = "0.1"
+flate2 = "0.2.0"
diff --git a/tests/unit/net/http_loader.rs b/tests/unit/net/http_loader.rs
new file mode 100644
index 00000000000..f007522b433
--- /dev/null
+++ b/tests/unit/net/http_loader.rs
@@ -0,0 +1,666 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 flate2::Compression;
+use flate2::write::{GzEncoder, DeflateEncoder};
+use hyper::header::{Headers, Location, ContentLength};
+use hyper::http::RawStatus;
+use hyper::method::Method;
+use hyper::status::StatusCode;
+use ipc_channel::ipc;
+use net::http_loader::{load, LoadError, HttpRequestFactory, HttpRequest, HttpResponse};
+use net::resource_task::new_resource_task;
+use net_traits::LoadData;
+use net_traits::{ResourceTask, ControlMsg, CookieSource};
+use std::borrow::Cow;
+use std::io::{self, Write, Read, Cursor};
+use url::Url;
+
+fn respond_with(body: Vec<u8>) -> MockResponse {
+ let mut headers = Headers::new();
+ respond_with_headers(body, &mut headers)
+}
+
+fn respond_with_headers(body: Vec<u8>, headers: &mut Headers) -> MockResponse {
+ headers.set(ContentLength(body.len() as u64));
+
+ MockResponse::new(
+ headers.clone(),
+ StatusCode::Ok,
+ RawStatus(200, Cow::Borrowed("Ok")),
+ body
+ )
+}
+
+fn read_response(reader: &mut Read) -> String {
+ let mut buf = vec![0; 1024];
+ match reader.read(&mut buf) {
+ Ok(len) if len > 0 => {
+ unsafe { buf.set_len(len); }
+ String::from_utf8(buf).unwrap()
+ },
+ Ok(_) => "".to_string(),
+ Err(e) => panic!("problem reading response {}", e)
+ }
+}
+
+struct MockResponse {
+ h: Headers,
+ sc: StatusCode,
+ sr: RawStatus,
+ msg: Cursor<Vec<u8>>
+}
+
+impl MockResponse {
+ fn new(h: Headers, sc: StatusCode, sr: RawStatus, msg: Vec<u8>) -> MockResponse {
+ MockResponse { h: h, sc: sc, sr: sr, msg: Cursor::new(msg) }
+ }
+}
+
+impl Read for MockResponse {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ self.msg.read(buf)
+ }
+}
+
+impl HttpResponse for MockResponse {
+ fn headers(&self) -> &Headers { &self.h }
+ fn status(&self) -> StatusCode { self.sc }
+ fn status_raw(&self) -> &RawStatus { &self.sr }
+}
+
+fn redirect_to(host: String) -> MockResponse {
+ let mut headers = Headers::new();
+ headers.set(Location(host.to_string()));
+
+ MockResponse::new(
+ headers,
+ StatusCode::MovedPermanently,
+ RawStatus(301, Cow::Borrowed("Moved Permanently")),
+ <[_]>::to_vec("".as_bytes())
+ )
+}
+
+
+enum ResponseType {
+ Redirect(String),
+ Text(Vec<u8>),
+ WithHeaders(Vec<u8>, Headers)
+}
+
+struct MockRequest {
+ headers: Headers,
+ t: ResponseType
+}
+
+impl MockRequest {
+ fn new(t: ResponseType) -> MockRequest {
+ MockRequest { headers: Headers::new(), t: t }
+ }
+}
+
+fn response_for_request_type(t: ResponseType) -> Result<MockResponse, LoadError> {
+ match t {
+ ResponseType::Redirect(location) => {
+ Ok(redirect_to(location))
+ },
+ ResponseType::Text(b) => {
+ Ok(respond_with(b))
+ },
+ ResponseType::WithHeaders(b, mut h) => {
+ Ok(respond_with_headers(b, &mut h))
+ }
+ }
+}
+
+impl HttpRequest for MockRequest {
+ type R = MockResponse;
+
+ fn headers_mut(&mut self) -> &mut Headers { &mut self.headers }
+
+ fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> {
+ response_for_request_type(self.t)
+ }
+}
+
+struct AssertRequestMustHaveHeaders {
+ expected_headers: Headers,
+ request_headers: Headers,
+ t: ResponseType
+}
+
+impl AssertRequestMustHaveHeaders {
+ fn new(t: ResponseType, expected_headers: Headers) -> Self {
+ AssertRequestMustHaveHeaders { expected_headers: expected_headers, request_headers: Headers::new(), t: t }
+ }
+}
+
+impl HttpRequest for AssertRequestMustHaveHeaders {
+ type R = MockResponse;
+
+ fn headers_mut(&mut self) -> &mut Headers { &mut self.request_headers }
+
+ fn send(self, _: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> {
+ for header in self.expected_headers.iter() {
+ assert!(self.request_headers.get_raw(header.name()).is_some());
+ assert_eq!(
+ self.request_headers.get_raw(header.name()).unwrap(),
+ self.expected_headers.get_raw(header.name()).unwrap()
+ )
+ }
+
+ response_for_request_type(self.t)
+ }
+}
+
+struct AssertMustHaveHeadersRequestFactory {
+ expected_headers: Headers,
+ body: Vec<u8>
+}
+
+impl HttpRequestFactory for AssertMustHaveHeadersRequestFactory {
+ type R = AssertRequestMustHaveHeaders;
+
+ fn create(&self, _: Url, _: Method) -> Result<AssertRequestMustHaveHeaders, LoadError> {
+ Ok(
+ AssertRequestMustHaveHeaders::new(
+ ResponseType::Text(self.body.clone()),
+ self.expected_headers.clone()
+ )
+ )
+ }
+}
+
+fn assert_cookie_for_domain(resource_mgr: &ResourceTask, domain: &str, cookie: &str) {
+ let (tx, rx) = ipc::channel().unwrap();
+ resource_mgr.send(ControlMsg::GetCookiesForUrl(Url::parse(&*domain).unwrap(),
+ tx,
+ CookieSource::HTTP)).unwrap();
+ if let Some(cookie_list) = rx.recv().unwrap() {
+ assert_eq!(cookie.to_string(), cookie_list);
+ } else {
+ assert_eq!(cookie.len(), 0);
+ }
+}
+
+struct AssertMustHaveBodyRequest {
+ expected_body: Option<Vec<u8>>,
+ headers: Headers,
+ t: ResponseType
+}
+
+impl AssertMustHaveBodyRequest {
+ fn new(t: ResponseType, expected_body: Option<Vec<u8>>) -> Self {
+ AssertMustHaveBodyRequest { expected_body: expected_body, headers: Headers::new(), t: t }
+ }
+}
+
+impl HttpRequest for AssertMustHaveBodyRequest {
+ type R = MockResponse;
+
+ fn headers_mut(&mut self) -> &mut Headers { &mut self.headers }
+
+ fn send(self, body: &Option<Vec<u8>>) -> Result<MockResponse, LoadError> {
+ assert_eq!(self.expected_body, *body);
+
+ response_for_request_type(self.t)
+ }
+}
+
+#[test]
+fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length_should_be_set_to_0() {
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = None;
+ load_data.method = Method::Post;
+
+ let mut content_length = Headers::new();
+ content_length.set_raw("Content-Length".to_owned(), vec![<[_]>::to_vec("0".as_bytes())]);
+
+ let _ = load::<AssertRequestMustHaveHeaders>(
+ load_data.clone(), resource_mgr, None,
+ &AssertMustHaveHeadersRequestFactory {
+ expected_headers: content_length,
+ body: <[_]>::to_vec(&[])
+ });
+}
+
+#[test]
+fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, url: Url, method: Method) -> Result<MockRequest, LoadError> {
+ if url.domain().unwrap() == "mozilla.com" {
+ assert_eq!(Method::Post, method);
+ Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_string())))
+ } else {
+ assert_eq!(Method::Get, method);
+ Ok(MockRequest::new(ResponseType::Text(<[_]>::to_vec("Yay!".as_bytes()))))
+ }
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.method = Method::Post;
+
+ let _ = load::<MockRequest>(load_data, resource_mgr, None, &Factory);
+}
+
+#[test]
+fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_content_encoding_deflate() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> {
+ let mut e = DeflateEncoder::new(Vec::new(), Compression::Default);
+ e.write(b"Yay!").unwrap();
+ let encoded_content = e.finish().unwrap();
+
+ let mut headers = Headers::new();
+ headers.set_raw("Content-Encoding", vec![b"deflate".to_vec()]);
+ Ok(MockRequest::new(ResponseType::WithHeaders(encoded_content, headers)))
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+ let mut response = load::<MockRequest>(load_data, resource_mgr.clone(), None, &Factory).unwrap();
+
+ assert_eq!(read_response(&mut response), "Yay!");
+}
+
+#[test]
+fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_content_encoding_gzip() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> {
+ let mut e = GzEncoder::new(Vec::new(), Compression::Default);
+ e.write(b"Yay!").unwrap();
+ let encoded_content = e.finish().unwrap();
+
+ let mut headers = Headers::new();
+ headers.set_raw("Content-Encoding", vec![b"gzip".to_vec()]);
+ Ok(MockRequest::new(ResponseType::WithHeaders(encoded_content, headers)))
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+ let mut response = load::<MockRequest>(load_data, resource_mgr.clone(), None, &Factory).unwrap();
+
+ assert_eq!(read_response(&mut response), "Yay!");
+}
+
+#[test]
+fn test_load_doesnt_send_request_body_on_any_redirect() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = AssertMustHaveBodyRequest;
+
+ fn create(&self, url: Url, _: Method) -> Result<AssertMustHaveBodyRequest, LoadError> {
+ if url.domain().unwrap() == "mozilla.com" {
+ Ok(
+ AssertMustHaveBodyRequest::new(
+ ResponseType::Redirect("http://mozilla.org".to_string()),
+ Some(<[_]>::to_vec("Body on POST!".as_bytes()))
+ )
+ )
+ } else {
+ Ok(
+ AssertMustHaveBodyRequest::new(
+ ResponseType::Text(<[_]>::to_vec("Yay!".as_bytes())),
+ None
+ )
+ )
+ }
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec("Body on POST!".as_bytes()));
+
+
+ let _ = load::<AssertMustHaveBodyRequest>(load_data, resource_mgr, None, &Factory);
+}
+
+#[test]
+fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_are_present() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> {
+ let content = <[_]>::to_vec("Yay!".as_bytes());
+ let mut headers = Headers::new();
+ headers.set_raw("Strict-Transport-Security", vec![b"max-age=31536000".to_vec()]);
+ Ok(MockRequest::new(ResponseType::WithHeaders(content, headers)))
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+
+ let load_data = LoadData::new(url.clone(), None);
+
+ let _ = load::<MockRequest>(load_data, resource_mgr.clone(), None, &Factory);
+
+ let (tx, rx) = ipc::channel().unwrap();
+ resource_mgr.send(ControlMsg::GetHostMustBeSecured("mozilla.com".to_string(), tx)).unwrap();
+
+ assert_eq!(rx.recv().unwrap(), false);
+}
+
+#[test]
+fn test_load_adds_host_to_sts_list_when_url_is_https_and_sts_headers_are_present() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> {
+ let content = <[_]>::to_vec("Yay!".as_bytes());
+ let mut headers = Headers::new();
+ headers.set_raw("Strict-Transport-Security", vec![b"max-age=31536000".to_vec()]);
+ Ok(MockRequest::new(ResponseType::WithHeaders(content, headers)))
+ }
+ }
+
+ let url = Url::parse("https://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+
+ let load_data = LoadData::new(url.clone(), None);
+
+ let _ = load::<MockRequest>(load_data, resource_mgr.clone(), None, &Factory);
+
+ let (tx, rx) = ipc::channel().unwrap();
+ resource_mgr.send(ControlMsg::GetHostMustBeSecured("mozilla.com".to_string(), tx)).unwrap();
+
+ assert!(rx.recv().unwrap());
+}
+
+#[test]
+fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_in_response() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, _: Url, _: Method) -> Result<MockRequest, LoadError> {
+ let content = <[_]>::to_vec("Yay!".as_bytes());
+ let mut headers = Headers::new();
+ headers.set_raw("set-cookie", vec![b"mozillaIs=theBest".to_vec()]);
+ Ok(MockRequest::new(ResponseType::WithHeaders(content, headers)))
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ assert_cookie_for_domain(&resource_mgr, "http://mozilla.com", "");
+
+ let load_data = LoadData::new(url.clone(), None);
+
+ let _ = load::<MockRequest>(load_data, resource_mgr.clone(), None, &Factory);
+
+ assert_cookie_for_domain(&resource_mgr, "http://mozilla.com", "mozillaIs=theBest");
+}
+
+#[test]
+fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_resource_manager() {
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ resource_mgr.send(ControlMsg::SetCookiesForUrl(Url::parse("http://mozilla.com").unwrap(),
+ "mozillaIs=theBest".to_string(),
+ CookieSource::HTTP)).unwrap();
+
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
+
+ let mut cookie = Headers::new();
+ cookie.set_raw("Cookie".to_owned(), vec![<[_]>::to_vec("mozillaIs=theBest".as_bytes())]);
+
+ let _ = load::<AssertRequestMustHaveHeaders>(
+ load_data.clone(), resource_mgr, None,
+ &AssertMustHaveHeadersRequestFactory {
+ expected_headers: cookie,
+ body: <[_]>::to_vec(&*load_data.data.unwrap())
+ });
+}
+
+#[test]
+fn test_load_sets_content_length_to_length_of_request_body() {
+ let content = "This is a request body";
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec(content.as_bytes()));
+
+ let mut content_len_headers = Headers::new();
+ let content_len = format!("{}", content.len());
+ content_len_headers.set_raw(
+ "Content-Length".to_owned(), vec![<[_]>::to_vec(&*content_len.as_bytes())]
+ );
+
+ let _ = load::<AssertRequestMustHaveHeaders>(
+ load_data.clone(), resource_mgr, None,
+ &AssertMustHaveHeadersRequestFactory {
+ expected_headers: content_len_headers,
+ body: <[_]>::to_vec(&*load_data.data.unwrap())
+ });
+}
+
+#[test]
+fn test_load_uses_explicit_accept_from_headers_in_load_data() {
+ let mut accept_headers = Headers::new();
+ accept_headers.set_raw("Accept".to_owned(), vec![b"text/html".to_vec()]);
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
+ load_data.headers.set_raw("Accept".to_owned(), vec![b"text/html".to_vec()]);
+
+ let _ = load::<AssertRequestMustHaveHeaders>(load_data, resource_mgr, None, &AssertMustHaveHeadersRequestFactory {
+ expected_headers: accept_headers,
+ body: <[_]>::to_vec("Yay!".as_bytes())
+ });
+}
+
+#[test]
+fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() {
+ let mut accept_headers = Headers::new();
+ accept_headers.set_raw(
+ "Accept".to_owned(), vec![b"text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8".to_vec()]
+ );
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
+
+ let _ = load::<AssertRequestMustHaveHeaders>(load_data, resource_mgr, None, &AssertMustHaveHeadersRequestFactory {
+ expected_headers: accept_headers,
+ body: <[_]>::to_vec("Yay!".as_bytes())
+ });
+}
+
+#[test]
+fn test_load_uses_explicit_accept_encoding_from_load_data_headers() {
+ let mut accept_encoding_headers = Headers::new();
+ accept_encoding_headers.set_raw("Accept-Encoding".to_owned(), vec![b"chunked".to_vec()]);
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
+ load_data.headers.set_raw("Accept-Encoding".to_owned(), vec![b"chunked".to_vec()]);
+
+ let _ = load::<AssertRequestMustHaveHeaders>(load_data, resource_mgr, None, &AssertMustHaveHeadersRequestFactory {
+ expected_headers: accept_encoding_headers,
+ body: <[_]>::to_vec("Yay!".as_bytes())
+ });
+}
+
+#[test]
+fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
+ let mut accept_encoding_headers = Headers::new();
+ accept_encoding_headers.set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]);
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let mut load_data = LoadData::new(url.clone(), None);
+ load_data.data = Some(<[_]>::to_vec("Yay!".as_bytes()));
+
+ let _ = load::<AssertRequestMustHaveHeaders>(load_data, resource_mgr, None, &AssertMustHaveHeadersRequestFactory {
+ expected_headers: accept_encoding_headers,
+ body: <[_]>::to_vec("Yay!".as_bytes())
+ });
+}
+
+#[test]
+fn test_load_errors_when_there_a_redirect_loop() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> {
+ if url.domain().unwrap() == "mozilla.com" {
+ Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_string())))
+ } else if url.domain().unwrap() == "mozilla.org" {
+ Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.com".to_string())))
+ } else {
+ panic!("unexpected host {:?}", url)
+ }
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+
+ match load::<MockRequest>(load_data, resource_mgr, None, &Factory) {
+ Err(LoadError::InvalidRedirect(_, msg)) => {
+ assert_eq!(msg, "redirect loop");
+ },
+ _ => panic!("expected max redirects to fail")
+ }
+}
+
+#[test]
+fn test_load_errors_when_there_is_too_many_redirects() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> {
+ if url.domain().unwrap() == "mozilla.com" {
+ Ok(MockRequest::new(ResponseType::Redirect(format!("{}/1", url.serialize()))))
+ } else {
+ panic!("unexpected host {:?}", url)
+ }
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+
+ match load::<MockRequest>(load_data, resource_mgr, None, &Factory) {
+ Err(LoadError::MaxRedirects(url)) => {
+ assert_eq!(url.domain().unwrap(), "mozilla.com")
+ },
+ _ => panic!("expected max redirects to fail")
+ }
+}
+
+#[test]
+fn test_load_follows_a_redirect() {
+ struct Factory;
+
+ impl HttpRequestFactory for Factory {
+ type R = MockRequest;
+
+ fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> {
+ if url.domain().unwrap() == "mozilla.com" {
+ Ok(MockRequest::new(ResponseType::Redirect("http://mozilla.org".to_string())))
+ } else if url.domain().unwrap() == "mozilla.org" {
+ Ok(
+ MockRequest::new(
+ ResponseType::Text(
+ <[_]>::to_vec("Yay!".as_bytes())
+ )
+ )
+ )
+ } else {
+ panic!("unexpected host {:?}", url)
+ }
+ }
+ }
+
+ let url = Url::parse("http://mozilla.com").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+
+ match load::<MockRequest>(load_data, resource_mgr, None, &Factory) {
+ Err(e) => panic!("expected to follow a redirect {:?}", e),
+ Ok(mut lr) => {
+ let response = read_response(&mut lr);
+ assert_eq!(response, "Yay!".to_string());
+ }
+ }
+}
+
+struct DontConnectFactory;
+
+impl HttpRequestFactory for DontConnectFactory {
+ type R = MockRequest;
+
+ fn create(&self, url: Url, _: Method) -> Result<MockRequest, LoadError> {
+ Err(LoadError::Connection(url, "should not have connected".to_string()))
+ }
+}
+
+#[test]
+fn test_load_errors_when_scheme_is_not_http_or_https() {
+ let url = Url::parse("ftp://not-supported").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+
+ match load::<MockRequest>(load_data, resource_mgr, None, &DontConnectFactory) {
+ Err(LoadError::UnsupportedScheme(_)) => {}
+ _ => panic!("expected ftp scheme to be unsupported")
+ }
+}
+
+#[test]
+fn test_load_errors_when_viewing_source_and_inner_url_scheme_is_not_http_or_https() {
+ let url = Url::parse("view-source:ftp://not-supported").unwrap();
+ let resource_mgr = new_resource_task("Test-agent".to_string(), None);
+ let load_data = LoadData::new(url.clone(), None);
+
+ match load::<MockRequest>(load_data, resource_mgr, None, &DontConnectFactory) {
+ Err(LoadError::UnsupportedScheme(_)) => {}
+ _ => panic!("expected ftp scheme to be unsupported")
+ }
+}
diff --git a/tests/unit/net/lib.rs b/tests/unit/net/lib.rs
index 3f737fc1783..8f7b0d1511f 100644
--- a/tests/unit/net/lib.rs
+++ b/tests/unit/net/lib.rs
@@ -10,9 +10,12 @@ extern crate net_traits;
extern crate url;
extern crate util;
extern crate time;
+extern crate hyper;
+extern crate flate2;
#[cfg(test)] mod cookie;
#[cfg(test)] mod data_loader;
#[cfg(test)] mod mime_classifier;
#[cfg(test)] mod resource_task;
#[cfg(test)] mod hsts;
+#[cfg(test)] mod http_loader;
diff --git a/tests/unit/net/mime_classifier.rs b/tests/unit/net/mime_classifier.rs
index b2e48926901..2c62878872e 100644
--- a/tests/unit/net/mime_classifier.rs
+++ b/tests/unit/net/mime_classifier.rs
@@ -434,7 +434,14 @@ fn test_sniff_utf_8_bom() {
#[test]
fn test_sniff_rss_feed() {
+ // RSS feeds
test_sniff_full(&PathBuf::from("text/xml/feed.rss"), "application", "rss+xml", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss.xml"), "application", "rss+xml", Some(("text", "html")));
+ // Not RSS feeds
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_1.xml"), "text", "html", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_2.xml"), "text", "html", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_3.xml"), "text", "html", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_4.xml"), "text", "html", Some(("text", "html")));
}
#[test]
diff --git a/tests/unit/net/parsable_mime/text/xml/rdf_rss.xml b/tests/unit/net/parsable_mime/text/xml/rdf_rss.xml
new file mode 100644
index 00000000000..4c58f82974e
--- /dev/null
+++ b/tests/unit/net/parsable_mime/text/xml/rdf_rss.xml
@@ -0,0 +1,7 @@
+<!-- Good format for a "RDF feed" -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_1.xml b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_1.xml
new file mode 100644
index 00000000000..f6e486c5960
--- /dev/null
+++ b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_1.xml
@@ -0,0 +1,7 @@
+<!-- Bad format for a "RDF feed" (space between "rdf:" and "RDF") -->
+<?xml version="1.0"?>
+<rdf: RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_2.xml b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_2.xml
new file mode 100644
index 00000000000..be8414382e5
--- /dev/null
+++ b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_2.xml
@@ -0,0 +1,3 @@
+<!-- Bad format for a "RDF feed" (2 missing URLs) -->
+<?xml version="1.0"?>
+<rdf:RDF/> \ No newline at end of file
diff --git a/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_3.xml b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_3.xml
new file mode 100644
index 00000000000..5f0f03f1e2d
--- /dev/null
+++ b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_3.xml
@@ -0,0 +1,6 @@
+<!-- Bad format for a "RDF feed" (one missing URL) -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_4.xml b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_4.xml
new file mode 100644
index 00000000000..c06a80cf1f8
--- /dev/null
+++ b/tests/unit/net/parsable_mime/text/xml/rdf_rss_ko_4.xml
@@ -0,0 +1,7 @@
+<!-- Bad format for a "RDF feed" (unexpected space in first URL) -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http: //www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/tests/unit/script/textinput.rs b/tests/unit/script/textinput.rs
index 313ab62fe0a..74891b52cae 100644
--- a/tests/unit/script/textinput.rs
+++ b/tests/unit/script/textinput.rs
@@ -9,9 +9,9 @@
use msg::constellation_msg::{Key, KeyModifiers};
-#[cfg(target_os="macos")]
+#[cfg(target_os = "macos")]
use msg::constellation_msg::SUPER;
-#[cfg(not(target_os="macos"))]
+#[cfg(not(target_os = "macos"))]
use msg::constellation_msg::CONTROL;
use script::clipboard_provider::DummyClipboardContext;
@@ -194,9 +194,9 @@ fn test_textinput_set_content() {
#[test]
fn test_clipboard_paste() {
- #[cfg(target_os="macos")]
+ #[cfg(target_os = "macos")]
const MODIFIERS: KeyModifiers = SUPER;
- #[cfg(not(target_os="macos"))]
+ #[cfg(not(target_os = "macos"))]
const MODIFIERS: KeyModifiers = CONTROL;
let mut textinput = TextInput::new(Lines::Single, "defg".to_owned(), DummyClipboardContext::new("abc"));
@@ -205,3 +205,57 @@ fn test_clipboard_paste() {
textinput.handle_keydown_aux(Key::V, MODIFIERS);
assert_eq!(textinput.get_content(), "abcdefg");
}
+
+#[test]
+fn test_textinput_cursor_position_correct_after_clearing_selection() {
+ let mut textinput = TextInput::new(Lines::Single, "abcdef".to_owned(), DummyClipboardContext::new(""));
+
+ // Single line - Forward
+ textinput.adjust_horizontal(3, Selection::Selected);
+ textinput.adjust_horizontal(1, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 3);
+
+ textinput.adjust_horizontal(-3, Selection::NotSelected);
+ textinput.adjust_horizontal(3, Selection::Selected);
+ textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 3);
+
+ // Single line - Backward
+ textinput.adjust_horizontal(-3, Selection::NotSelected);
+ textinput.adjust_horizontal(3, Selection::Selected);
+ textinput.adjust_horizontal(-1, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 0);
+
+ textinput.adjust_horizontal(-3, Selection::NotSelected);
+ textinput.adjust_horizontal(3, Selection::Selected);
+ textinput.adjust_horizontal_by_one(Direction::Backward, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 0);
+
+
+ let mut textinput = TextInput::new(Lines::Multiple, "abc\nde\nf".to_owned(), DummyClipboardContext::new(""));
+
+ // Multiline - Forward
+ textinput.adjust_horizontal(4, Selection::Selected);
+ textinput.adjust_horizontal(1, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point.line, 1);
+
+ textinput.adjust_horizontal(-4, Selection::NotSelected);
+ textinput.adjust_horizontal(4, Selection::Selected);
+ textinput.adjust_horizontal_by_one(Direction::Forward, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point.line, 1);
+
+ // Multiline - Backward
+ textinput.adjust_horizontal(-4, Selection::NotSelected);
+ textinput.adjust_horizontal(4, Selection::Selected);
+ textinput.adjust_horizontal(-1, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point.line, 0);
+
+ textinput.adjust_horizontal(-4, Selection::NotSelected);
+ textinput.adjust_horizontal(4, Selection::Selected);
+ textinput.adjust_horizontal_by_one(Direction::Backward, Selection::NotSelected);
+ assert_eq!(textinput.edit_point.index, 0);
+ assert_eq!(textinput.edit_point.line, 0);
+}
diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini
index cbd4f34dbf1..1c00f118a49 100644
--- a/tests/wpt/include.ini
+++ b/tests/wpt/include.ini
@@ -73,18 +73,6 @@ skip: true
skip: false
[workers]
skip: false
- [constructors]
- skip: false
- [SharedWorker]
- skip: true
- [semantics]
- skip: false
- [navigation]
- skip: true
- [reporting-errors]
- skip: true
- [structured-clone]
- skip: true
[XMLHttpRequest]
skip: false
[old-tests]
diff --git a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-069.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-069.htm.ini
deleted file mode 100644
index 3393052ea38..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-069.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[abs-pos-non-replaced-vlr-069.htm]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-177.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-177.htm.ini
deleted file mode 100644
index e1c3b4f4d05..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-177.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[abs-pos-non-replaced-vlr-177.htm]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-193.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-193.htm.ini
deleted file mode 100644
index 5e854311604..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vlr-193.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[abs-pos-non-replaced-vlr-193.htm]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-176.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-176.htm.ini
deleted file mode 100644
index eefff3cffd7..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-176.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[abs-pos-non-replaced-vrl-176.htm]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-192.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-192.htm.ini
deleted file mode 100644
index ae93a9937bd..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/abs-pos-non-replaced-vrl-192.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[abs-pos-non-replaced-vrl-192.htm]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata-css/css21_dev/html4/absolute-replaced-width-015.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/absolute-replaced-width-015.htm.ini
deleted file mode 100644
index d17e0d4951e..00000000000
--- a/tests/wpt/metadata-css/css21_dev/html4/absolute-replaced-width-015.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[absolute-replaced-width-015.htm]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini
index cb01cd8f47d..080c6d4e7d5 100644
--- a/tests/wpt/metadata/html/dom/interfaces.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.html.ini
@@ -8430,9 +8430,6 @@
[Worker interface: operation terminate()]
expected: FAIL
- [Worker interface: attribute onerror]
- expected: FAIL
-
[SharedWorker interface: existence and properties of interface object]
expected: FAIL
diff --git a/tests/wpt/metadata/url/interfaces.html.ini b/tests/wpt/metadata/url/interfaces.html.ini
index f1a85fdfc35..17a665ab572 100644
--- a/tests/wpt/metadata/url/interfaces.html.ini
+++ b/tests/wpt/metadata/url/interfaces.html.ini
@@ -3,42 +3,12 @@
[URL interface: operation domainToUnicode(ScalarValueString)]
expected: FAIL
- [URL interface: attribute href]
- expected: FAIL
-
[URL interface: attribute origin]
expected: FAIL
- [URL interface: attribute protocol]
- expected: FAIL
-
- [URL interface: attribute username]
- expected: FAIL
-
- [URL interface: attribute password]
- expected: FAIL
-
- [URL interface: attribute host]
- expected: FAIL
-
- [URL interface: attribute hostname]
- expected: FAIL
-
- [URL interface: attribute port]
- expected: FAIL
-
- [URL interface: attribute pathname]
- expected: FAIL
-
- [URL interface: attribute search]
- expected: FAIL
-
[URL interface: attribute searchParams]
expected: FAIL
- [URL interface: attribute hash]
- expected: FAIL
-
[URL interface: new URL("http://foo") must inherit property "origin" with the proper type (3)]
expected: FAIL
diff --git a/tests/wpt/metadata/workers/constructors/SharedWorker/__dir__.ini b/tests/wpt/metadata/workers/constructors/SharedWorker/__dir__.ini
new file mode 100644
index 00000000000..168df4e0769
--- /dev/null
+++ b/tests/wpt/metadata/workers/constructors/SharedWorker/__dir__.ini
@@ -0,0 +1 @@
+disabled: SharedWorker
diff --git a/tests/wpt/metadata/workers/semantics/navigation/001.html.ini b/tests/wpt/metadata/workers/semantics/navigation/001.html.ini
new file mode 100644
index 00000000000..b3538369e2e
--- /dev/null
+++ b/tests/wpt/metadata/workers/semantics/navigation/001.html.ini
@@ -0,0 +1,3 @@
+[001.html]
+ type: testharness
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/workers/semantics/navigation/002.html.ini b/tests/wpt/metadata/workers/semantics/navigation/002.html.ini
new file mode 100644
index 00000000000..23e8bb1452d
--- /dev/null
+++ b/tests/wpt/metadata/workers/semantics/navigation/002.html.ini
@@ -0,0 +1,5 @@
+[002.html]
+ type: testharness
+ [navigating 2]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/workers/semantics/reporting-errors/__dir__.ini b/tests/wpt/metadata/workers/semantics/reporting-errors/__dir__.ini
new file mode 100644
index 00000000000..168df4e0769
--- /dev/null
+++ b/tests/wpt/metadata/workers/semantics/reporting-errors/__dir__.ini
@@ -0,0 +1 @@
+disabled: SharedWorker
diff --git a/tests/wpt/metadata/workers/semantics/structured-clone/__dir__.ini b/tests/wpt/metadata/workers/semantics/structured-clone/__dir__.ini
new file mode 100644
index 00000000000..879844e9bd2
--- /dev/null
+++ b/tests/wpt/metadata/workers/semantics/structured-clone/__dir__.ini
@@ -0,0 +1 @@
+disabled: Broken somehow