diff options
520 files changed, 10457 insertions, 3857 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1ffcbc67969..3036586fe49 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ If you're looking for easy bugs, have a look at the [E-Easy issue tag](https://g comment, or you can ask for a review in `#servo` on `irc.mozilla.org`. - Add tests relevant to the fixed bug or new feature. For a DOM change this - will usually be a content test; for layout, a reftest. See our [testing + will usually be a web platform test; for layout, a reftest. See our [testing guide](https://github.com/mozilla/servo/wiki/Testing) for more information. For specific git instructions, see [GitHub & Critic PR handling 101](https://github.com/mozilla/servo/wiki/Github-&-Critic-PR-handling-101). diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index bc186d02ccf..00000000000 --- a/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] - -name = "not-the-toml-you-re-looking-for" -version = "0.0.1" -authors = ["The Servo Project Developers"] - -build = "support/not-the-toml-you-re-looking-for.rs" - -[lib] -name = "not-the-toml-you-re-looking-for" diff --git a/ORGANIZATION.md b/ORGANIZATION.md index 90727186290..b90fae7a969 100644 --- a/ORGANIZATION.md +++ b/ORGANIZATION.md @@ -30,8 +30,6 @@ special integration: ## Tests -* `tests/contenttest.rs`: Content (JavaScript) test runner. -* `tests/content`: Content tests. * `tests/reftest.rs`: Reference (layout) test runner. * `tests/ref`: Reference tests. * `tests/html`: Manual test cases and examples. diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index a682f1069bb..df07dbd1de0 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -16,6 +16,17 @@ git = "https://github.com/servo/rust-cssparser" [dependencies.geom] git = "https://github.com/servo/rust-geom" +[dependencies.gleam] +git = "https://github.com/servo/gleam" + +[dependencies.glutin] +git = "https://github.com/servo/glutin" +branch = "servo" +features = ["headless"] + +[dependencies.msg] +path = "../msg" + [dependencies.util] path = "../util" diff --git a/components/canvas/canvas_msg.rs b/components/canvas/canvas_msg.rs new file mode 100644 index 00000000000..86e1dcc6f81 --- /dev/null +++ b/components/canvas/canvas_msg.rs @@ -0,0 +1,62 @@ +/* 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 canvas_paint_task::{FillOrStrokeStyle, LineCapStyle, LineJoinStyle}; +use geom::matrix2d::Matrix2D; +use geom::point::Point2D; +use geom::rect::Rect; +use geom::size::Size2D; +use std::sync::mpsc::{Sender}; + +#[derive(Clone)] +pub enum CanvasMsg { + Canvas2d(Canvas2dMsg), + Common(CanvasCommonMsg), + WebGL(CanvasWebGLMsg), +} + +#[derive(Clone)] +pub enum Canvas2dMsg { + Arc(Point2D<f32>, f32, f32, f32, bool), + ArcTo(Point2D<f32>, Point2D<f32>, f32), + DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool), + DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool), + BeginPath, + BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>), + ClosePath, + ClearRect(Rect<f32>), + Fill, + FillRect(Rect<f32>), + GetImageData(Rect<f64>, Size2D<f64>, Sender<Vec<u8>>), + LineTo(Point2D<f32>), + MoveTo(Point2D<f32>), + PutImageData(Vec<u8>, Rect<f64>, Option<Rect<f64>>), + QuadraticCurveTo(Point2D<f32>, Point2D<f32>), + Rect(Rect<f32>), + RestoreContext, + SaveContext, + StrokeRect(Rect<f32>), + Stroke, + SetFillStyle(FillOrStrokeStyle), + SetStrokeStyle(FillOrStrokeStyle), + SetLineWidth(f32), + SetLineCap(LineCapStyle), + SetLineJoin(LineJoinStyle), + SetMiterLimit(f32), + SetGlobalAlpha(f32), + SetTransform(Matrix2D<f32>), +} + +#[derive(Clone)] +pub enum CanvasWebGLMsg { + Clear(u32), + ClearColor(f32, f32, f32, f32), +} + +#[derive(Clone)] +pub enum CanvasCommonMsg { + Close, + Recreate(Size2D<i32>), + SendPixelContents(Sender<Vec<u8>>), +} diff --git a/components/canvas/canvas_paint_task.rs b/components/canvas/canvas_paint_task.rs index 8a1fc0679c4..2eceb25331f 100644 --- a/components/canvas/canvas_paint_task.rs +++ b/components/canvas/canvas_paint_task.rs @@ -6,6 +6,7 @@ use azure::azure::AzFloat; use azure::azure_hl::{DrawTarget, SurfaceFormat, BackendType, StrokeOptions, DrawOptions, Pattern}; use azure::azure_hl::{ColorPattern, PathBuilder, JoinStyle, CapStyle, DrawSurfaceOptions, Filter}; use azure::azure_hl::{GradientStop, LinearGradientPattern, RadialGradientPattern, ExtendMode}; +use canvas_msg::{CanvasMsg, Canvas2dMsg, CanvasCommonMsg}; use geom::matrix2d::Matrix2D; use geom::point::Point2D; use geom::rect::Rect; @@ -16,41 +17,10 @@ use util::vec::byte_swap; use cssparser::RGBA; use std::borrow::ToOwned; +use std::mem; use std::num::{Float, ToPrimitive}; use std::sync::mpsc::{channel, Sender}; -#[derive(Clone)] -pub enum CanvasMsg { - FillRect(Rect<f32>), - ClearRect(Rect<f32>), - StrokeRect(Rect<f32>), - BeginPath, - ClosePath, - Fill, - Stroke, - DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool), - DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool), - MoveTo(Point2D<f32>), - LineTo(Point2D<f32>), - QuadraticCurveTo(Point2D<f32>, Point2D<f32>), - BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>), - Arc(Point2D<f32>, f32, f32, f32, bool), - ArcTo(Point2D<f32>, Point2D<f32>, f32), - SetFillStyle(FillOrStrokeStyle), - SetStrokeStyle(FillOrStrokeStyle), - SetLineWidth(f32), - SetLineCap(LineCapStyle), - SetLineJoin(LineJoinStyle), - SetMiterLimit(f32), - SetTransform(Matrix2D<f32>), - SetGlobalAlpha(f32), - Recreate(Size2D<i32>), - SendPixelContents(Sender<Vec<u8>>), - GetImageData(Rect<f64>, Size2D<f64>, Sender<Vec<u8>>), - PutImageData(Vec<u8>, Rect<f64>, Option<Rect<f64>>), - Close, -} - impl<'a> CanvasPaintTask<'a> { /// It reads image data from the canvas /// canvas_size: The size of the canvas we're reading from @@ -92,7 +62,7 @@ impl<'a> CanvasPaintTask<'a> { source_rect: Rect<f64>, dest_rect: Rect<f64>, smoothing_enabled: bool) { - // From spec https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage + // From spec https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage // When scaling up, if the imageSmoothingEnabled attribute is set to true, the user agent should attempt // to apply a smoothing algorithm to the image data when it is scaled. // Otherwise, the image must be rendered using nearest-neighbor interpolation. @@ -109,7 +79,7 @@ impl<'a> CanvasPaintTask<'a> { image_size, image_size.width * 4, SurfaceFormat::B8G8R8A8); let draw_surface_options = DrawSurfaceOptions::new(filter, true); - let draw_options = DrawOptions::new(self.draw_options.alpha, 0); + let draw_options = DrawOptions::new(self.state.draw_options.alpha, 0); self.drawtarget.draw_surface(source_surface, dest_rect.to_azfloat(), @@ -186,28 +156,43 @@ impl<'a> CanvasPaintTask<'a> { pub struct CanvasPaintTask<'a> { drawtarget: DrawTarget, + /// TODO(pcwalton): Support multiple paths. + path_builder: PathBuilder, + state: CanvasPaintState<'a>, + saved_states: Vec<CanvasPaintState<'a>>, +} + +#[derive(Clone)] +struct CanvasPaintState<'a> { draw_options: DrawOptions, fill_style: Pattern, stroke_style: Pattern, stroke_opts: StrokeOptions<'a>, - /// TODO(pcwalton): Support multiple paths. - path_builder: PathBuilder, /// The current 2D transform matrix. transform: Matrix2D<f32>, } +impl<'a> CanvasPaintState<'a> { + fn new() -> CanvasPaintState<'a> { + CanvasPaintState { + draw_options: DrawOptions::new(1.0, 0), + fill_style: Pattern::Color(ColorPattern::new(color::black())), + stroke_style: Pattern::Color(ColorPattern::new(color::black())), + stroke_opts: StrokeOptions::new(1.0, JoinStyle::MiterOrBevel, CapStyle::Butt, 10.0, &[]), + transform: Matrix2D::identity(), + } + } +} + impl<'a> CanvasPaintTask<'a> { fn new(size: Size2D<i32>) -> CanvasPaintTask<'a> { let draw_target = CanvasPaintTask::create(size); let path_builder = draw_target.create_path_builder(); CanvasPaintTask { drawtarget: draw_target, - draw_options: DrawOptions::new(1.0, 0), - fill_style: Pattern::Color(ColorPattern::new(color::black())), - stroke_style: Pattern::Color(ColorPattern::new(color::black())), - stroke_opts: StrokeOptions::new(1.0, JoinStyle::MiterOrBevel, CapStyle::Butt, 10.0, &[]), path_builder: path_builder, - transform: Matrix2D::identity(), + state: CanvasPaintState::new(), + saved_states: Vec::new(), } } @@ -218,55 +203,80 @@ impl<'a> CanvasPaintTask<'a> { loop { match port.recv().unwrap() { - CanvasMsg::FillRect(ref rect) => painter.fill_rect(rect), - CanvasMsg::StrokeRect(ref rect) => painter.stroke_rect(rect), - CanvasMsg::ClearRect(ref rect) => painter.clear_rect(rect), - CanvasMsg::BeginPath => painter.begin_path(), - CanvasMsg::ClosePath => painter.close_path(), - CanvasMsg::Fill => painter.fill(), - CanvasMsg::Stroke => painter.stroke(), - CanvasMsg::DrawImage(imagedata, image_size, dest_rect, source_rect, smoothing_enabled) => { - painter.draw_image(imagedata, image_size, dest_rect, source_rect, smoothing_enabled) - } - CanvasMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled) => { - painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled) - } - CanvasMsg::MoveTo(ref point) => painter.move_to(point), - CanvasMsg::LineTo(ref point) => painter.line_to(point), - CanvasMsg::QuadraticCurveTo(ref cp, ref pt) => { - painter.quadratic_curve_to(cp, pt) - } - CanvasMsg::BezierCurveTo(ref cp1, ref cp2, ref pt) => { - painter.bezier_curve_to(cp1, cp2, pt) - } - CanvasMsg::Arc(ref center, radius, start, end, ccw) => { - painter.arc(center, radius, start, end, ccw) - } - CanvasMsg::ArcTo(ref cp1, ref cp2, radius) => { - painter.arc_to(cp1, cp2, radius) - } - CanvasMsg::SetFillStyle(style) => painter.set_fill_style(style), - CanvasMsg::SetStrokeStyle(style) => painter.set_stroke_style(style), - CanvasMsg::SetLineWidth(width) => painter.set_line_width(width), - CanvasMsg::SetLineCap(cap) => painter.set_line_cap(cap), - CanvasMsg::SetLineJoin(join) => painter.set_line_join(join), - CanvasMsg::SetMiterLimit(limit) => painter.set_miter_limit(limit), - CanvasMsg::SetTransform(ref matrix) => painter.set_transform(matrix), - CanvasMsg::SetGlobalAlpha(alpha) => painter.set_global_alpha(alpha), - CanvasMsg::Recreate(size) => painter.recreate(size), - CanvasMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan), - CanvasMsg::GetImageData(dest_rect, canvas_size, chan) => painter.get_image_data(dest_rect, canvas_size, chan), - CanvasMsg::PutImageData(imagedata, image_data_rect, dirty_rect) - => painter.put_image_data(imagedata, image_data_rect, dirty_rect), - CanvasMsg::Close => break, + CanvasMsg::Canvas2d(message) => { + match message { + Canvas2dMsg::FillRect(ref rect) => painter.fill_rect(rect), + Canvas2dMsg::StrokeRect(ref rect) => painter.stroke_rect(rect), + Canvas2dMsg::ClearRect(ref rect) => painter.clear_rect(rect), + Canvas2dMsg::BeginPath => painter.begin_path(), + Canvas2dMsg::ClosePath => painter.close_path(), + Canvas2dMsg::Fill => painter.fill(), + Canvas2dMsg::Stroke => painter.stroke(), + Canvas2dMsg::DrawImage(imagedata, image_size, dest_rect, source_rect, smoothing_enabled) => { + painter.draw_image(imagedata, image_size, dest_rect, source_rect, smoothing_enabled) + } + Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled) => { + painter.draw_image_self(image_size, dest_rect, source_rect, smoothing_enabled) + } + Canvas2dMsg::MoveTo(ref point) => painter.move_to(point), + Canvas2dMsg::LineTo(ref point) => painter.line_to(point), + Canvas2dMsg::Rect(ref rect) => painter.rect(rect), + Canvas2dMsg::QuadraticCurveTo(ref cp, ref pt) => { + painter.quadratic_curve_to(cp, pt) + } + Canvas2dMsg::BezierCurveTo(ref cp1, ref cp2, ref pt) => { + painter.bezier_curve_to(cp1, cp2, pt) + } + Canvas2dMsg::Arc(ref center, radius, start, end, ccw) => { + painter.arc(center, radius, start, end, ccw) + } + Canvas2dMsg::ArcTo(ref cp1, ref cp2, radius) => { + painter.arc_to(cp1, cp2, radius) + } + Canvas2dMsg::RestoreContext => painter.restore_context_state(), + Canvas2dMsg::SaveContext => painter.save_context_state(), + Canvas2dMsg::SetFillStyle(style) => painter.set_fill_style(style), + Canvas2dMsg::SetStrokeStyle(style) => painter.set_stroke_style(style), + Canvas2dMsg::SetLineWidth(width) => painter.set_line_width(width), + Canvas2dMsg::SetLineCap(cap) => painter.set_line_cap(cap), + Canvas2dMsg::SetLineJoin(join) => painter.set_line_join(join), + Canvas2dMsg::SetMiterLimit(limit) => painter.set_miter_limit(limit), + Canvas2dMsg::SetTransform(ref matrix) => painter.set_transform(matrix), + Canvas2dMsg::SetGlobalAlpha(alpha) => painter.set_global_alpha(alpha), + Canvas2dMsg::GetImageData(dest_rect, canvas_size, chan) => painter.get_image_data(dest_rect, canvas_size, chan), + Canvas2dMsg::PutImageData(imagedata, image_data_rect, dirty_rect) + => painter.put_image_data(imagedata, image_data_rect, dirty_rect), + } + }, + CanvasMsg::Common(message) => { + match message { + CanvasCommonMsg::Close => break, + CanvasCommonMsg::Recreate(size) => painter.recreate(size), + CanvasCommonMsg::SendPixelContents(chan) => + painter.send_pixel_contents(chan), + } + }, + CanvasMsg::WebGL(_) => panic!("Wrong message sent to Canvas2D task"), } } }); chan } + fn save_context_state(&mut self) { + self.saved_states.push(self.state.clone()); + } + + fn restore_context_state(&mut self) { + if let Some(state) = self.saved_states.pop() { + mem::replace(&mut self.state, state); + self.drawtarget.set_transform(&self.state.transform); + } + } + fn fill_rect(&self, rect: &Rect<f32>) { - self.drawtarget.fill_rect(rect, self.fill_style.to_pattern_ref(), Some(&self.draw_options)); + self.drawtarget.fill_rect(rect, self.state.fill_style.to_pattern_ref(), + Some(&self.state.draw_options)); } fn clear_rect(&self, rect: &Rect<f32>) { @@ -274,9 +284,9 @@ impl<'a> CanvasPaintTask<'a> { } fn stroke_rect(&self, rect: &Rect<f32>) { - match self.stroke_style { + match self.state.stroke_style { Pattern::Color(ref color) => { - self.drawtarget.stroke_rect(rect, color, &self.stroke_opts, &self.draw_options) + self.drawtarget.stroke_rect(rect, color, &self.state.stroke_opts, &self.state.draw_options) } _ => { // TODO(pcwalton) @@ -293,9 +303,9 @@ impl<'a> CanvasPaintTask<'a> { } fn fill(&self) { - match self.fill_style { + match self.state.fill_style { Pattern::Color(ref color) => { - self.drawtarget.fill(&self.path_builder.finish(), color, &self.draw_options); + self.drawtarget.fill(&self.path_builder.finish(), color, &self.state.draw_options); } _ => { // TODO(pcwalton) @@ -304,10 +314,10 @@ impl<'a> CanvasPaintTask<'a> { } fn stroke(&self) { - match self.stroke_style { + match self.state.stroke_style { Pattern::Color(ref color) => { self.drawtarget.stroke(&self.path_builder.finish(), - color, &self.stroke_opts, &self.draw_options); + color, &self.state.stroke_opts, &self.state.draw_options); } _ => { // TODO @@ -342,6 +352,15 @@ impl<'a> CanvasPaintTask<'a> { self.path_builder.line_to(*point) } + fn rect(&self, rect: &Rect<f32>) { + self.path_builder.move_to(Point2D(rect.origin.x, rect.origin.y)); + self.path_builder.line_to(Point2D(rect.origin.x + rect.size.width, rect.origin.y)); + self.path_builder.line_to(Point2D(rect.origin.x + rect.size.width, + rect.origin.y + rect.size.height)); + self.path_builder.line_to(Point2D(rect.origin.x, rect.origin.y + rect.size.height)); + self.path_builder.close(); + } + fn quadratic_curve_to(&self, cp: &Point2D<AzFloat>, endpoint: &Point2D<AzFloat>) { @@ -420,36 +439,36 @@ impl<'a> CanvasPaintTask<'a> { } fn set_fill_style(&mut self, style: FillOrStrokeStyle) { - self.fill_style = style.to_azure_pattern(&self.drawtarget) + self.state.fill_style = style.to_azure_pattern(&self.drawtarget) } fn set_stroke_style(&mut self, style: FillOrStrokeStyle) { - self.stroke_style = style.to_azure_pattern(&self.drawtarget) + self.state.stroke_style = style.to_azure_pattern(&self.drawtarget) } fn set_line_width(&mut self, width: f32) { - self.stroke_opts.line_width = width; + self.state.stroke_opts.line_width = width; } fn set_line_cap(&mut self, cap: LineCapStyle) { - self.stroke_opts.line_cap = cap.to_azure_style(); + self.state.stroke_opts.line_cap = cap.to_azure_style(); } fn set_line_join(&mut self, join: LineJoinStyle) { - self.stroke_opts.line_join = join.to_azure_style(); + self.state.stroke_opts.line_join = join.to_azure_style(); } fn set_miter_limit(&mut self, limit: f32) { - self.stroke_opts.miter_limit = limit; + self.state.stroke_opts.miter_limit = limit; } fn set_transform(&mut self, transform: &Matrix2D<f32>) { - self.transform = *transform; + self.state.transform = *transform; self.drawtarget.set_transform(transform) } fn set_global_alpha(&mut self, alpha: f32) { - self.draw_options.alpha = alpha; + self.state.draw_options.alpha = alpha; } fn create(size: Size2D<i32>) -> DrawTarget { diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs index 2b5c51feec1..5feab435394 100644 --- a/components/canvas/lib.rs +++ b/components/canvas/lib.rs @@ -11,6 +11,10 @@ extern crate cssparser; extern crate geom; extern crate gfx; extern crate util; - +extern crate gleam; +extern crate msg; +extern crate glutin; pub mod canvas_paint_task; +pub mod webgl_paint_task; +pub mod canvas_msg; diff --git a/components/canvas/webgl_paint_task.rs b/components/canvas/webgl_paint_task.rs new file mode 100644 index 00000000000..1afcf20089c --- /dev/null +++ b/components/canvas/webgl_paint_task.rs @@ -0,0 +1,112 @@ +/* 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 canvas_msg::{CanvasWebGLMsg, CanvasCommonMsg, CanvasMsg}; +use geom::size::Size2D; + +use gleam::gl; +use gleam::gl::types::{GLint, GLsizei}; + +use util::task::spawn_named; + +use std::borrow::ToOwned; +use std::sync::mpsc::{channel, Sender}; +use util::vec::byte_swap; + +use glutin::{HeadlessRendererBuilder}; + +pub struct WebGLPaintTask { + size: Size2D<i32>, +} + +impl WebGLPaintTask { + fn new(size: Size2D<i32>) -> WebGLPaintTask { + WebGLPaintTask::create(size); + WebGLPaintTask { + size: size, + } + } + + pub fn start(size: Size2D<i32>) -> Sender<CanvasMsg> { + let (chan, port) = channel::<CanvasMsg>(); + spawn_named("WebGLTask".to_owned(), move || { + let mut painter = WebGLPaintTask::new(size); + painter.init(); + loop { + match port.recv().unwrap() { + CanvasMsg::WebGL(message) => { + match message { + CanvasWebGLMsg::Clear(mask) => painter.clear(mask), + CanvasWebGLMsg::ClearColor(r, g, b, a) => painter.clear_color(r, g, b, a), + } + }, + CanvasMsg::Common(message) => { + match message { + CanvasCommonMsg::Close => break, + CanvasCommonMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan), + CanvasCommonMsg::Recreate(size) => painter.recreate(size), + } + }, + CanvasMsg::Canvas2d(_) => panic!("Wrong message sent to WebGLTask"), + } + } + }); + chan + } + + fn create(size: Size2D<i32>) { + // It creates OpenGL context + let context = HeadlessRendererBuilder::new(size.width as u32, size.height as u32).build().unwrap(); + unsafe { + context.make_current(); + } + } + + fn init(&self) { + let framebuffer_ids = gl::gen_framebuffers(1); + gl::bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]); + + let texture_ids = gl::gen_textures(1); + gl::bind_texture(gl::TEXTURE_2D, texture_ids[0]); + + gl::tex_image_2d(gl::TEXTURE_2D, 0, gl::RGB as GLint, self.size.width as GLsizei, + self.size.height as GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, None); + gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint); + gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint); + + gl::framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, + texture_ids[0], 0); + gl::bind_texture(gl::TEXTURE_2D, 0); + + gl::viewport(0 as GLint, 0 as GLint, + self.size.width as GLsizei, self.size.height as GLsizei); + } + + fn clear(&self, mask: u32) { + gl::clear(mask); + } + + fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) { + gl::clear_color(r, g, b, a); + } + + fn send_pixel_contents(&mut self, chan: Sender<Vec<u8>>) { + // FIXME(#5652, dmarcos) Instead of a readback strategy we have + // to layerize the canvas + let mut pixels = gl::read_pixels(0, 0, + self.size.width as gl::GLsizei, + self.size.height as gl::GLsizei, + gl::RGBA, gl::UNSIGNED_BYTE); + + // rgba -> bgra + byte_swap(pixels.as_mut_slice()); + chan.send(pixels).unwrap(); + } + + fn recreate(&mut self, size: Size2D<i32>) { + self.size = size; + self.init(); + } + +} diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index ff8082bcf1f..d9fc51499fb 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -31,6 +31,9 @@ path = "../net_traits" [dependencies.util] path = "../util" +[dependencies.webdriver_server] +path = "../webdriver_server" + [dependencies.devtools_traits] path = "../devtools_traits" diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 9f0e98e2e30..0520fa4859f 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -32,7 +32,7 @@ use std::collections::HashMap; use std::io::{self, Write}; use std::marker::PhantomData; use std::mem::replace; -use std::sync::mpsc::{Receiver, channel}; +use std::sync::mpsc::{Sender, Receiver, channel}; use url::Url; use util::cursor::Cursor; use util::geometry::PagePx; @@ -87,6 +87,9 @@ pub struct Constellation<LTF, STF> { /// The next free ID to assign to a frame. next_frame_id: FrameId, + /// Pipeline ID that has currently focused element for key events. + focus_pipeline_id: Option<PipelineId>, + /// Navigation operations that are in progress. pending_frames: Vec<FrameChange>, @@ -198,6 +201,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { next_pipeline_id: PipelineId(0), root_frame_id: None, next_frame_id: FrameId(0), + focus_pipeline_id: None, time_profiler_chan: time_profiler_chan, mem_profiler_chan: mem_profiler_chan, window_size: WindowSizeData { @@ -383,6 +387,14 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { subpage_id, event); } + ConstellationMsg::GetRootPipeline(resp_chan) => { + debug!("constellation got get root pipeline message"); + self.handle_get_root_pipeline(resp_chan); + } + ConstellationMsg::FocusMsg(pipeline_id) => { + debug!("constellation got focus message"); + self.handle_focus_msg(pipeline_id); + } } true } @@ -590,6 +602,11 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { self.pipeline_to_frame_map.get(&pipeline_id).map(|id| *id) }).unwrap(); + // Check if the currently focused pipeline is the pipeline being replaced + // (or a child of it). This has to be done here, before the current + // frame tree is modified below. + let update_focus_pipeline = self.focused_pipeline_in_tree(frame_id); + // Get the ids for the previous and next pipelines. let (prev_pipeline_id, next_pipeline_id) = { let frame = self.mut_frame(frame_id); @@ -617,6 +634,13 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { (prev, next) }; + // If the currently focused pipeline is the one being changed (or a child + // of the pipeline being changed) then update the focus pipeline to be + // the replacement. + if update_focus_pipeline { + self.focus_pipeline_id = Some(next_pipeline_id); + } + // Suspend the old pipeline, and resume the new one. self.pipeline(prev_pipeline_id).freeze(); self.pipeline(next_pipeline_id).thaw(); @@ -641,10 +665,16 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { } fn handle_key_msg(&self, key: Key, state: KeyState, mods: KeyModifiers) { - match self.root_frame_id { - Some(root_frame_id) => { - let root_frame = self.frame(root_frame_id); - let pipeline = self.pipeline(root_frame.current); + // Send to the explicitly focused pipeline (if it exists), or the root + // frame's current pipeline. If neither exist, fall back to sending to + // the compositor below. + let target_pipeline_id = self.focus_pipeline_id.or(self.root_frame_id.map(|frame_id| { + self.frame(frame_id).current + })); + + match target_pipeline_id { + Some(target_pipeline_id) => { + let pipeline = self.pipeline(target_pipeline_id); let ScriptControlChan(ref chan) = pipeline.script_chan; let event = CompositorEvent::KeyEvent(key, state, mods); chan.send(ConstellationControlMsg::SendEvent(pipeline.id, @@ -679,7 +709,47 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { pipeline.trigger_mozbrowser_event(subpage_id, event); } + fn handle_get_root_pipeline(&mut self, resp_chan: Sender<Option<PipelineId>>) { + let pipeline_id = self.root_frame_id.map(|frame_id| { + let frame = self.frames.get(&frame_id).unwrap(); + frame.current + }); + resp_chan.send(pipeline_id).unwrap(); + } + + fn focus_parent_pipeline(&self, pipeline_id: PipelineId) { + // Send a message to the parent of the provided pipeline (if it exists) + // telling it to mark the iframe element as focused. + if let Some((containing_pipeline_id, subpage_id)) = self.pipeline(pipeline_id).parent_info { + let pipeline = self.pipeline(containing_pipeline_id); + let ScriptControlChan(ref script_channel) = pipeline.script_chan; + let event = ConstellationControlMsg::FocusIFrameMsg(containing_pipeline_id, + subpage_id); + script_channel.send(event).unwrap(); + + self.focus_parent_pipeline(containing_pipeline_id); + } + } + + fn handle_focus_msg(&mut self, pipeline_id: PipelineId) { + self.focus_pipeline_id = Some(pipeline_id); + + // Focus parent iframes recursively + self.focus_parent_pipeline(pipeline_id); + } + fn add_or_replace_pipeline_in_frame_tree(&mut self, frame_change: FrameChange) { + + // If the currently focused pipeline is the one being changed (or a child + // of the pipeline being changed) then update the focus pipeline to be + // the replacement. + if let Some(old_pipeline_id) = frame_change.old_pipeline_id { + let old_frame_id = *self.pipeline_to_frame_map.get(&old_pipeline_id).unwrap(); + if self.focused_pipeline_in_tree(old_frame_id) { + self.focus_pipeline_id = Some(frame_change.new_pipeline_id); + } + } + let evicted_frames = match frame_change.old_pipeline_id { Some(old_pipeline_id) => { // The new pipeline is replacing an old one. @@ -911,8 +981,20 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { } } + fn focused_pipeline_in_tree(&self, frame_id: FrameId) -> bool { + self.focus_pipeline_id.map_or(false, |pipeline_id| { + self.pipeline_exists_in_tree(pipeline_id, Some(frame_id)) + }) + } + fn pipeline_is_in_current_frame(&self, pipeline_id: PipelineId) -> bool { - self.current_frame_tree_iter(self.root_frame_id) + self.pipeline_exists_in_tree(pipeline_id, self.root_frame_id) + } + + fn pipeline_exists_in_tree(&self, + pipeline_id: PipelineId, + root_frame_id: Option<FrameId>) -> bool { + self.current_frame_tree_iter(root_frame_id) .any(|current_frame| current_frame.current == pipeline_id) } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index 23f8f76d0ba..e98f03f4a73 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -27,6 +27,7 @@ extern crate net_traits; #[macro_use] extern crate util; extern crate gleam; +extern crate webdriver_server; extern crate libc; extern crate time; diff --git a/components/devtools/actor.rs b/components/devtools/actor.rs index 125080328f0..1fdd2af5c14 100644 --- a/components/devtools/actor.rs +++ b/components/devtools/actor.rs @@ -4,6 +4,7 @@ /// General actor system infrastructure. +use rustc_serialize::json; use std::any::{Any, TypeId}; use std::collections::HashMap; use std::cell::{Cell, RefCell}; @@ -11,7 +12,7 @@ use std::mem::{replace, transmute}; use std::net::TcpStream; use std::raw::TraitObject; use std::sync::{Arc, Mutex}; -use rustc_serialize::json; +use time::PreciseTime; /// A common trait for all devtools actors that encompasses an immutable name /// and the ability to process messages that are directed to particular actors. @@ -82,6 +83,7 @@ pub struct ActorRegistry { script_actors: RefCell<HashMap<String, String>>, shareable: Option<Arc<Mutex<ActorRegistry>>>, next: Cell<u32>, + start_stamp: PreciseTime, } impl ActorRegistry { @@ -94,6 +96,7 @@ impl ActorRegistry { script_actors: RefCell::new(HashMap::new()), shareable: None, next: Cell::new(0), + start_stamp: PreciseTime::now(), } } @@ -115,6 +118,11 @@ impl ActorRegistry { self.shareable.as_ref().unwrap().clone() } + /// Get start stamp when registry was started + pub fn get_start_stamp(&self) -> PreciseTime { + self.start_stamp.clone() + } + pub fn register_script_actor(&self, script_id: String, actor: String) { println!("registering {} ({})", actor, script_id); let mut script_actors = self.script_actors.borrow_mut(); diff --git a/components/devtools/actors/timeline.rs b/components/devtools/actors/timeline.rs index 94ab37ce3c7..6ea92626ae3 100644 --- a/components/devtools/actors/timeline.rs +++ b/components/devtools/actors/timeline.rs @@ -4,7 +4,7 @@ use core::iter::FromIterator; use msg::constellation_msg::PipelineId; -use rustc_serialize::json; +use rustc_serialize::{json, Encoder, Encodable}; use std::cell::RefCell; use std::collections::{HashMap, VecDeque}; use std::net::TcpStream; @@ -12,7 +12,7 @@ use std::old_io::timer::sleep; use std::sync::{Arc, Mutex}; use std::time::duration::Duration; use std::sync::mpsc::{channel, Sender, Receiver}; -use time::precise_time_ns; +use time::PreciseTime; use actor::{Actor, ActorRegistry}; use actors::memory::{MemoryActor, TimelineMemoryReply}; @@ -40,6 +40,7 @@ struct Emitter { stream: TcpStream, markers: Vec<TimelineMarkerReply>, registry: Arc<Mutex<ActorRegistry>>, + start_stamp: PreciseTime, framerate_actor: Option<String>, memory_actor: Option<String>, @@ -54,20 +55,20 @@ struct IsRecordingReply { #[derive(RustcEncodable)] struct StartReply { from: String, - value: u64 + value: HighResolutionStamp, } #[derive(RustcEncodable)] struct StopReply { from: String, - value: u64 + value: HighResolutionStamp, } #[derive(RustcEncodable)] struct TimelineMarkerReply { name: String, - start: u64, - end: u64, + start: HighResolutionStamp, + end: HighResolutionStamp, stack: Option<Vec<()>>, endStack: Option<Vec<()>>, } @@ -77,14 +78,14 @@ struct MarkersEmitterReply { __type__: String, markers: Vec<TimelineMarkerReply>, from: String, - endTime: u64, + endTime: HighResolutionStamp, } #[derive(RustcEncodable)] struct MemoryEmitterReply { __type__: String, from: String, - delta: u64, + delta: HighResolutionStamp, measurement: TimelineMemoryReply, } @@ -92,10 +93,30 @@ struct MemoryEmitterReply { struct FramerateEmitterReply { __type__: String, from: String, - delta: u64, + delta: HighResolutionStamp, timestamps: Vec<u64>, } +/// HighResolutionStamp is struct that contains duration in milliseconds +/// with accuracy to microsecond that shows how much time has passed since +/// actor registry inited +/// analog https://w3c.github.io/hr-time/#sec-DOMHighResTimeStamp +struct HighResolutionStamp(f64); + +impl HighResolutionStamp { + fn new(start_stamp: PreciseTime, time: PreciseTime) -> HighResolutionStamp { + let duration = start_stamp.to(time).num_microseconds() + .expect("Too big duration in microseconds"); + HighResolutionStamp(duration as f64 / 1000 as f64) + } +} + +impl Encodable for HighResolutionStamp { + fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { + self.0.encode(s) + } +} + static DEFAULT_TIMELINE_DATA_PULL_TIMEOUT: usize = 200; //ms impl TimelineActor { @@ -233,6 +254,7 @@ impl Actor for TimelineActor { } let emitter = Emitter::new(self.name(), registry.get_shareable(), + registry.get_start_stamp(), stream.try_clone().unwrap(), self.memory_actor.borrow().clone(), self.framerate_actor.borrow().clone()); @@ -241,7 +263,8 @@ impl Actor for TimelineActor { let msg = StartReply { from: self.name(), - value: precise_time_ns(), + value: HighResolutionStamp::new(registry.get_start_stamp(), + PreciseTime::now()), }; stream.write_json_packet(&msg); true @@ -250,7 +273,8 @@ impl Actor for TimelineActor { "stop" => { let msg = StopReply { from: self.name(), - value: precise_time_ns() + value: HighResolutionStamp::new(registry.get_start_stamp(), + PreciseTime::now()), }; stream.write_json_packet(&msg); @@ -289,6 +313,7 @@ impl Actor for TimelineActor { impl Emitter { pub fn new(name: String, registry: Arc<Mutex<ActorRegistry>>, + start_stamp: PreciseTime, stream: TcpStream, memory_actor_name: Option<String>, framerate_actor_name: Option<String>) -> Emitter { @@ -298,6 +323,7 @@ impl Emitter { stream: stream, markers: Vec::new(), registry: registry, + start_stamp: start_stamp, framerate_actor: framerate_actor_name, memory_actor: memory_actor_name, @@ -307,20 +333,20 @@ impl Emitter { fn add_marker(&mut self, start_payload: TimelineMarker, end_payload: TimelineMarker) -> () { self.markers.push(TimelineMarkerReply { name: start_payload.name, - start: start_payload.time, - end: end_payload.time, + 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, }); } fn send(&mut self) -> () { - let end_time = precise_time_ns(); + let end_time = PreciseTime::now(); let reply = MarkersEmitterReply { __type__: "markers".to_string(), markers: Vec::from_iter(self.markers.drain()), from: self.from.clone(), - endTime: end_time, + endTime: HighResolutionStamp::new(self.start_stamp, end_time), }; self.stream.write_json_packet(&reply); @@ -331,7 +357,7 @@ impl Emitter { let framerateReply = FramerateEmitterReply { __type__: "framerate".to_string(), from: framerate_actor.name(), - delta: end_time, + delta: HighResolutionStamp::new(self.start_stamp, end_time), timestamps: framerate_actor.take_pending_ticks(), }; self.stream.write_json_packet(&framerateReply); @@ -343,7 +369,7 @@ impl Emitter { let memoryReply = MemoryEmitterReply { __type__: "memory".to_string(), from: memory_actor.name(), - delta: end_time, + delta: HighResolutionStamp::new(self.start_stamp, end_time), measurement: memory_actor.measure(), }; self.stream.write_json_packet(&memoryReply); diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs index 90e9718728a..e2d06a7665b 100644 --- a/components/devtools/lib.rs +++ b/components/devtools/lib.rs @@ -114,6 +114,8 @@ fn run_server(sender: Sender<DevtoolsControlMsg>, let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new(); + let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); + /// Process the input from a single devtools client until EOF. fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) { @@ -152,13 +154,12 @@ fn run_server(sender: Sender<DevtoolsControlMsg>, ids: (PipelineId, Option<WorkerId>), scriptSender: Sender<DevtoolScriptControlMsg>, actor_pipelines: &mut HashMap<PipelineId, String>, + actor_workers: &mut HashMap<(PipelineId, WorkerId), String>, page_info: DevtoolsPageInfo) { let mut actors = actors.lock().unwrap(); let (pipeline, worker_id) = ids; - let mut actor_workers: HashMap<(PipelineId, WorkerId), String> = HashMap::new(); - //TODO: move all this actor creation into a constructor method on TabActor let (tab, console, inspector, timeline) = { let console = ConsoleActor { @@ -269,7 +270,7 @@ fn run_server(sender: Sender<DevtoolsControlMsg>, Ok(DevtoolsControlMsg::ServerExitMsg) | Err(RecvError) => break, Ok(DevtoolsControlMsg::NewGlobal(ids, scriptSender, pageinfo)) => handle_new_global(actors.clone(), ids, scriptSender, &mut actor_pipelines, - pageinfo), + &mut actor_workers, pageinfo), Ok(DevtoolsControlMsg::SendConsoleMessage(id, console_message)) => handle_console_message(actors.clone(), id, console_message, &actor_pipelines), diff --git a/components/devtools_traits/lib.rs b/components/devtools_traits/lib.rs index 851a8e6da1b..c77fb34c6ee 100644 --- a/components/devtools_traits/lib.rs +++ b/components/devtools_traits/lib.rs @@ -96,7 +96,7 @@ pub enum TracingMetadata { pub struct TimelineMarker { pub name: String, pub metadata: TracingMetadata, - pub time: u64, + pub time: time::PreciseTime, pub stack: Option<Vec<()>>, } @@ -159,7 +159,7 @@ impl TimelineMarker { TimelineMarker { name: name, metadata: metadata, - time: time::precise_time_ns(), + time: time::PreciseTime::now(), stack: None, } } diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index b5b935c88d2..1a12ec4a37c 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -34,6 +34,7 @@ use libc::uintptr_t; use paint_task::PaintLayer; use msg::compositor_msg::LayerId; use net_traits::image::base::Image; +use util::opts; use util::cursor::Cursor; use util::linked_list::prepend_from; use util::geometry::{self, Au, MAX_RECT, ZERO_RECT}; @@ -170,7 +171,7 @@ impl DisplayList { let doit = |items: &Vec<DisplayItem>| { for item in items.iter() { match *item { - DisplayItem::SolidColorClass(ref solid_color) => println!("{:?} SolidColor. {:?}", indentation, solid_color.base.bounds), + DisplayItem::SolidColorClass(ref solid_color) => println!("{} SolidColor. {:?}", indentation, solid_color.base.bounds), DisplayItem::TextClass(ref text) => println!("{:?} Text. {:?}", indentation, text.base.bounds), DisplayItem::ImageClass(ref image) => println!("{:?} Image. {:?}", indentation, image.base.bounds), DisplayItem::BorderClass(ref border) => println!("{:?} Border. {:?}", indentation, border.base.bounds), @@ -184,14 +185,11 @@ impl DisplayList { doit(&(self.all_display_items())); if self.children.len() != 0 { - println!("{} Children stacking contexts list length: {}", indentation, self.children.len()); - for subitem in self.children.iter() { - doit(&subitem.display_list.all_display_items()); - if subitem.display_list.children.len() != 0 { - // Rant: String doesn't have a substr() method that won't overflow if the - // selected range is bigger than the string length. - subitem.display_list.print_items(indentation.clone()+&indentation[0..min_length]); - } + println!("{} Children stacking contexts list length: {}", + indentation, + self.children.len()); + for sublist in self.children.iter() { + sublist.display_list.print_items(indentation.clone()+&indentation[0..min_length]); } } } @@ -283,6 +281,11 @@ impl StackingContext { let display_list = DisplayListOptimizer::new(tile_bounds).optimize(&*self.display_list); + if opts::get().dump_display_list_optimized { + println!("**** optimized display list. Tile bounds: {:?}", tile_bounds); + display_list.print_items(String::from_str("*")); + } + // Sort positioned children according to z-index. let mut positioned_children = SmallVec8::new(); for kid in display_list.children.iter() { diff --git a/components/gfx/filters.rs b/components/gfx/filters.rs index 948f2cdfc3d..cfabcf20324 100644 --- a/components/gfx/filters.rs +++ b/components/gfx/filters.rs @@ -8,15 +8,18 @@ use azure::AzFloat; use azure::azure_hl::{ColorMatrixAttribute, ColorMatrixInput, CompositeInput, DrawTarget}; use azure::azure_hl::{FilterNode, FilterType, LinearTransferAttribute, LinearTransferInput}; use azure::azure_hl::{Matrix5x4, TableTransferAttribute, TableTransferInput}; +use azure::azure_hl::{GaussianBlurAttribute, GaussianBlurInput}; use std::num::Float; use style::computed_values::filter; +use util::geometry::Au; /// Creates a filter pipeline from a set of CSS filters. Returns the destination end of the filter /// pipeline and the opacity. pub fn create_filters(draw_target: &DrawTarget, temporary_draw_target: &DrawTarget, - style_filters: &filter::T) + style_filters: &filter::T, + accumulated_blur_radius: &mut Au) -> (FilterNode, AzFloat) { let mut opacity = 1.0; let mut filter = draw_target.create_filter(FilterType::Composite); @@ -91,6 +94,14 @@ pub fn create_filters(draw_target: &DrawTarget, contrast.set_input(LinearTransferInput, &filter); filter = contrast } + filter::Filter::Blur(amount) => { + *accumulated_blur_radius = accumulated_blur_radius.clone() + amount; + let amount = amount.to_frac32_px(); + let blur = draw_target.create_filter(FilterType::GaussianBlur); + blur.set_attribute(GaussianBlurAttribute::StdDeviation(amount)); + blur.set_input(GaussianBlurInput, &filter); + filter = blur + } } } (filter, opacity) @@ -107,6 +118,23 @@ pub fn temporary_draw_target_needed_for_style_filters(filters: &filter::T) -> bo false } +// If there is one or more blur filters, we need to know the blur ammount +// to expand the draw target size. +pub fn calculate_accumulated_blur(style_filters: &filter::T) -> Au { + let mut accum_blur = Au::new(0); + for style_filter in style_filters.filters.iter() { + match *style_filter { + filter::Filter::Blur(amount) => { + accum_blur = accum_blur.clone() + amount; + } + _ => continue, + } + } + + accum_blur +} + + /// Creates a grayscale 5x4 color matrix per CSS-FILTERS § 12.1.1. fn grayscale(amount: AzFloat) -> Matrix5x4 { Matrix5x4 { diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs index 7f2ab8f9a55..be289eb940f 100644 --- a/components/gfx/paint_context.rs +++ b/components/gfx/paint_context.rs @@ -909,12 +909,30 @@ impl<'a> PaintContext<'a> { } // FIXME(pcwalton): This surface might be bigger than necessary and waste memory. - let size = self.draw_target.get_size(); - let size = Size2D(size.width, size.height); + let size = self.draw_target.get_size(); //Az size. + let mut size = Size2D(size.width, size.height); //Geom::Size. + + // Pre-calculate if there is a blur expansion need. + let accum_blur = filters::calculate_accumulated_blur(filters); + let mut matrix = self.draw_target.get_transform(); + if accum_blur > Au(0) { + // Set the correct size. + let side_inflation = accum_blur * BLUR_INFLATION_FACTOR; + size = Size2D(size.width + (side_inflation.to_nearest_px() * 2) as i32, size.height + (side_inflation.to_nearest_px() * 2) as i32); + + // Calculate the transform matrix. + let old_transform = self.draw_target.get_transform(); + let inflated_size = Rect(Point2D(0.0, 0.0), Size2D(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, + -temporary_draw_target_bounds.origin.y as AzFloat).mul(&old_transform); + } let temporary_draw_target = self.draw_target.create_similar_draw_target(&size, self.draw_target.get_format()); - temporary_draw_target.set_transform(&self.draw_target.get_transform()); + + temporary_draw_target.set_transform(&matrix); temporary_draw_target } @@ -932,18 +950,36 @@ impl<'a> PaintContext<'a> { // Set up transforms. let old_transform = self.draw_target.get_transform(); self.draw_target.set_transform(&Matrix2D::identity()); - temporary_draw_target.set_transform(&Matrix2D::identity()); + let rect = Rect(Point2D(0.0, 0.0), self.draw_target.get_size().to_azure_size()); + + let rect_temporary = Rect(Point2D(0.0, 0.0), temporary_draw_target.get_size().to_azure_size()); // Create the Azure filter pipeline. + let mut accum_blur = Au(0); let (filter_node, opacity) = filters::create_filters(&self.draw_target, temporary_draw_target, - filters); + filters, + &mut accum_blur); // Perform the blit operation. - let rect = Rect(Point2D(0.0, 0.0), self.draw_target.get_size().to_azure_size()); let mut draw_options = DrawOptions::new(opacity, 0); draw_options.set_composition_op(blend_mode.to_azure_composition_op()); - self.draw_target.draw_filter(&filter_node, &rect, &rect.origin, draw_options); + + // If there is a blur expansion, shift the transform and update the size. + if accum_blur > Au(0) { + // Remove both the transient clip and the stacking context clip, because we may need to + // draw outside the stacking context's clip. + self.remove_transient_clip_if_applicable(); + self.pop_clip_if_applicable(); + + debug!("######### use expanded Rect."); + self.draw_target.draw_filter(&filter_node, &rect_temporary, &rect_temporary.origin, draw_options); + self.push_clip_if_applicable(); + } else { + debug!("######### use regular Rect."); + self.draw_target.draw_filter(&filter_node, &rect, &rect.origin, draw_options); + } + self.draw_target.set_transform(&old_transform); } diff --git a/components/layout/animation.rs b/components/layout/animation.rs index 571228afccb..258ac7d0a39 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -93,7 +93,7 @@ pub fn tick_all_animations(layout_task: &LayoutTask, rw_data: &mut LayoutTaskDat let running_animations = mem::replace(&mut rw_data.running_animations, Vec::new()); let now = clock_ticks::precise_time_s(); for running_animation in running_animations.into_iter() { - layout_task.tick_animation(running_animation, rw_data); + layout_task.tick_animation(&running_animation, rw_data); if now < running_animation.end_time { // Keep running the animation if it hasn't expired. diff --git a/components/layout/block.rs b/components/layout/block.rs index e24dd869894..e616a952643 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -721,7 +721,7 @@ impl BlockFlow { /// Return true if this has a replaced fragment. /// /// Text, Images, Inline Block and - // Canvas (https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements) + // Canvas (https://html.spec.whatwg.org/multipage/#replaced-elements) // fragments are considered as replaced fragments fn is_replaced_content(&self) -> bool { match self.fragment.specific { diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index f440424cf1a..3e1af9c16b8 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -12,7 +12,7 @@ use azure::azure_hl::Color; use block::BlockFlow; -use canvas::canvas_paint_task::CanvasMsg::SendPixelContents; +use canvas::canvas_msg::{CanvasMsg, CanvasCommonMsg}; use context::LayoutContext; use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER}; use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo}; @@ -790,6 +790,10 @@ impl FragmentDisplayListBuilding for Fragment { relative_containing_block_mode: WritingMode, background_and_border_level: BackgroundAndBorderLevel, clip: &ClippingRegion) { + if self.style().get_inheritedbox().visibility != visibility::T::visible { + return + } + // Compute the fragment position relative to the parent stacking context. If the fragment // itself establishes a stacking context, then the origin of its position will be (0, 0) // for the purposes of this computation. @@ -807,10 +811,6 @@ impl FragmentDisplayListBuilding for Fragment { stacking_relative_flow_origin, self); - if self.style().get_inheritedbox().visibility != visibility::T::visible { - return - } - if !stacking_relative_border_box.intersects(&layout_context.shared.dirty) { debug!("Fragment::build_display_list: Did not intersect..."); return @@ -1004,7 +1004,7 @@ impl FragmentDisplayListBuilding for Fragment { let (sender, receiver) = channel::<Vec<u8>>(); let canvas_data = match canvas_fragment_info.renderer { Some(ref renderer) => { - renderer.lock().unwrap().send(SendPixelContents(sender)).unwrap(); + renderer.lock().unwrap().send(CanvasMsg::Common(CanvasCommonMsg::SendPixelContents(sender))).unwrap(); receiver.recv().unwrap() }, None => repeat(0xFFu8).take(width * height * 4).collect(), @@ -1253,6 +1253,11 @@ impl BlockFlowDisplayListBuilding for BlockFlow { layout_context: &LayoutContext, background_border_level: BackgroundAndBorderLevel) { // Add the box that starts the block context. + let clip = if self.fragment.establishes_stacking_context() { + self.base.clip.translate(&-self.base.stacking_relative_position) + } else { + self.base.clip.clone() + }; self.fragment.build_display_list(display_list, layout_context, &self.base.stacking_relative_position, @@ -1263,7 +1268,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { .absolute_position_info .relative_containing_block_mode, background_border_level, - &self.base.clip); + &clip); // Add children. for kid in self.base.children.iter_mut() { diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index cfaa8d87bf4..4ddea7d62c8 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -6,7 +6,7 @@ #![deny(unsafe_code)] -use canvas::canvas_paint_task::CanvasMsg; +use canvas::canvas_msg::CanvasMsg; use css::node_style::StyledNode; use context::LayoutContext; use floats::ClearType; diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index c31fbb0bab9..054b8f51dc9 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -923,7 +923,7 @@ impl LayoutTask { animation::tick_all_animations(self, &mut rw_data) } - pub fn tick_animation<'a>(&'a self, animation: Animation, rw_data: &mut LayoutTaskData) { + pub fn tick_animation<'a>(&'a self, animation: &Animation, rw_data: &mut LayoutTaskData) { let reflow_info = Reflow { goal: ReflowGoal::ForDisplay, page_clip_rect: MAX_RECT, diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index e528553bbc2..d1e92547bb9 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -32,7 +32,7 @@ #![allow(unsafe_code)] -use canvas::canvas_paint_task::CanvasMsg; +use canvas::canvas_msg::CanvasMsg; use context::SharedLayoutContext; use css::node_style::StyledNode; use incremental::RestyleDamage; diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index d1d2822e3fc..0f911a7e523 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -194,6 +194,13 @@ bitflags! { } } +/// Specifies the type of focus event that is sent to a pipeline +#[derive(Copy, PartialEq)] +pub enum FocusType { + Element, // The first focus message - focus the element itself + Parent, // Focusing a parent element (an iframe) +} + /// Messages from the compositor and script to the constellation. pub enum Msg { Exit, @@ -218,6 +225,10 @@ pub enum Msg { ChangeRunningAnimationsState(PipelineId, bool), /// Requests that the constellation instruct layout to begin a new tick of the animation. TickAnimation(PipelineId), + // Request that the constellation send the current root pipeline id over a provided channel + GetRootPipeline(Sender<Option<PipelineId>>), + /// Notifies the constellation that this frame has received focus. + FocusMsg(PipelineId), } // https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events diff --git a/components/net/about_loader.rs b/components/net/about_loader.rs index cd7d40671fd..11533c353f4 100644 --- a/components/net/about_loader.rs +++ b/components/net/about_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata}; +use net_traits::{LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::Done; use mime_classifier::MIMEClassifier; use resource_task::start_sending; @@ -18,10 +18,9 @@ use std::borrow::IntoCow; use std::fs::PathExt; use std::sync::Arc; -pub fn factory(mut load_data: LoadData, classifier: Arc<MIMEClassifier>) { +pub fn factory(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Arc<MIMEClassifier>) { match load_data.url.non_relative_scheme_data().unwrap() { "blank" => { - let start_chan = load_data.consumer; let chan = start_sending(start_chan, Metadata { final_url: load_data.url, content_type: Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]))), @@ -40,11 +39,10 @@ pub fn factory(mut load_data: LoadData, classifier: Arc<MIMEClassifier>) { load_data.url = Url::from_file_path(&*path).unwrap(); } _ => { - let start_chan = load_data.consumer; start_sending(start_chan, Metadata::default(load_data.url)) .send(Done(Err("Unknown about: URL.".to_string()))).unwrap(); return } }; - file_loader::factory(load_data, classifier) + file_loader::factory(load_data, start_chan, classifier) } diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs index 03ec60be3a8..5b86af53851 100644 --- a/components/net/data_loader.rs +++ b/components/net/data_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{LoadData, Metadata}; +use net_traits::{LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; use resource_task::start_sending; @@ -13,16 +13,15 @@ use hyper::mime::Mime; use std::sync::Arc; use url::{percent_decode, SchemeData}; -pub fn factory(load_data: LoadData, _classifier: Arc<MIMEClassifier>) { +pub fn factory(load_data: LoadData, senders: LoadConsumer, _classifier: Arc<MIMEClassifier>) { // NB: we don't spawn a new task. // Hypothesis: data URLs are too small for parallel base64 etc. to be worth it. // Should be tested at some point. // Left in separate function to allow easy moving to a task, if desired. - load(load_data) + load(load_data, senders) } -pub fn load(load_data: LoadData) { - let start_chan = load_data.consumer; +pub fn load(load_data: LoadData, start_chan: LoadConsumer) { let url = load_data.url; assert!(&*url.scheme == "data"); diff --git a/components/net/file_loader.rs b/components/net/file_loader.rs index 64539c29477..c2a1d672bd7 100644 --- a/components/net/file_loader.rs +++ b/components/net/file_loader.rs @@ -2,17 +2,16 @@ * 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 net_traits::{LoadData, Metadata, ProgressMsg}; +use net_traits::{LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; -use resource_task::{start_sending, start_sending_sniffed}; +use resource_task::{start_sending, start_sending_sniffed, ProgressSender}; use std::borrow::ToOwned; use std::fs::File; use std::io::Read; use std::path::PathBuf; use std::sync::Arc; -use std::sync::mpsc::Sender; use util::task::spawn_named; static READ_SIZE: usize = 8192; @@ -34,7 +33,7 @@ fn read_block(reader: &mut File) -> Result<ReadStatus, String> { } } -fn read_all(reader: &mut File, progress_chan: &Sender<ProgressMsg>) +fn read_all(reader: &mut File, progress_chan: &ProgressSender) -> Result<(), String> { loop { match try!(read_block(reader)) { @@ -44,9 +43,8 @@ fn read_all(reader: &mut File, progress_chan: &Sender<ProgressMsg>) } } -pub fn factory(load_data: LoadData, classifier: Arc<MIMEClassifier>) { +pub fn factory(load_data: LoadData, senders: LoadConsumer, classifier: Arc<MIMEClassifier>) { let url = load_data.url; - let start_chan = load_data.consumer; assert!(&*url.scheme == "file"); spawn_named("file_loader".to_owned(), move || { let metadata = Metadata::default(url.clone()); @@ -58,24 +56,24 @@ pub fn factory(load_data: LoadData, classifier: Arc<MIMEClassifier>) { let res = read_block(reader); let (res, progress_chan) = match res { Ok(ReadStatus::Partial(buf)) => { - let progress_chan = start_sending_sniffed(start_chan, metadata, + let progress_chan = start_sending_sniffed(senders, metadata, classifier, &buf); progress_chan.send(Payload(buf)).unwrap(); (read_all(reader, &progress_chan), progress_chan) } Ok(ReadStatus::EOF) | Err(_) => - (res.map(|_| ()), start_sending(start_chan, metadata)), + (res.map(|_| ()), start_sending(senders, metadata)), }; progress_chan.send(Done(res)).unwrap(); } Err(e) => { - let progress_chan = start_sending(start_chan, metadata); + let progress_chan = start_sending(senders, metadata); progress_chan.send(Done(Err(e.description().to_string()))).unwrap(); } } } Err(_) => { - let progress_chan = start_sending(start_chan, metadata); + let progress_chan = start_sending(senders, metadata); progress_chan.send(Done(Err(url.to_string()))).unwrap(); } } diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index d544c307401..0ac6980bb69 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use net_traits::{ControlMsg, CookieSource, LoadData, LoadResponse, Metadata}; +use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; use resource_task::{start_sending_opt, start_sending_sniffed_opt}; @@ -32,13 +32,13 @@ use url::{Url, UrlParser}; use std::borrow::ToOwned; pub fn factory(cookies_chan: Sender<ControlMsg>) - -> Box<Invoke<(LoadData, Arc<MIMEClassifier>)> + Send> { - box move |(load_data, classifier)| { - spawn_named("http_loader".to_owned(), move || load(load_data, classifier, cookies_chan)) + -> Box<Invoke<(LoadData, LoadConsumer, Arc<MIMEClassifier>)> + Send> { + box move |(load_data, senders, classifier)| { + spawn_named("http_loader".to_owned(), move || load(load_data, senders, classifier, cookies_chan)) } } -fn send_error(url: Url, err: String, start_chan: Sender<LoadResponse>) { +fn send_error(url: Url, err: String, start_chan: LoadConsumer) { let mut metadata: Metadata = Metadata::default(url); metadata.status = None; @@ -66,13 +66,12 @@ fn read_block<R: Read>(reader: &mut R) -> Result<ReadResult, ()> { } } -fn load(mut load_data: LoadData, classifier: Arc<MIMEClassifier>, cookies_chan: Sender<ControlMsg>) { +fn load(mut load_data: LoadData, start_chan: LoadConsumer, classifier: Arc<MIMEClassifier>, cookies_chan: Sender<ControlMsg>) { // 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. let max_redirects = 50; let mut iters = 0; - let start_chan = load_data.consumer; let mut url = load_data.url.clone(); let mut redirected_to = HashSet::new(); @@ -140,8 +139,8 @@ reason: \"certificate verify failed\" }]"; ) => { let mut image = resources_dir_path(); image.push("badcert.html"); - let load_data = LoadData::new(Url::from_file_path(&*image).unwrap(), start_chan); - file_loader::factory(load_data, classifier); + let load_data = LoadData::new(Url::from_file_path(&*image).unwrap()); + file_loader::factory(load_data, start_chan, classifier); return; }, Err(e) => { @@ -340,7 +339,7 @@ reason: \"certificate verify failed\" }]"; } fn send_data<R: Read>(reader: &mut R, - start_chan: Sender<LoadResponse>, + start_chan: LoadConsumer, metadata: Metadata, classifier: Arc<MIMEClassifier>) { let (progress_chan, mut chunk) = { diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs index 9952190c23b..15c48d111d9 100644 --- a/components/net/resource_task.rs +++ b/components/net/resource_task.rs @@ -12,8 +12,8 @@ use cookie_storage::CookieStorage; use cookie; use mime_classifier::MIMEClassifier; -use net_traits::{ControlMsg, LoadData, LoadResponse}; -use net_traits::{Metadata, ProgressMsg, ResourceTask}; +use net_traits::{ControlMsg, LoadData, LoadResponse, LoadConsumer}; +use net_traits::{Metadata, ProgressMsg, ResourceTask, AsyncResponseTarget, ResponseAction}; use net_traits::ProgressMsg::Done; use util::opts; use util::task::spawn_named; @@ -58,22 +58,44 @@ pub fn global_init() { } } +pub enum ProgressSender { + Channel(Sender<ProgressMsg>), + Listener(Box<AsyncResponseTarget>), +} + +impl ProgressSender { + //XXXjdm return actual error + pub fn send(&self, msg: ProgressMsg) -> Result<(), ()> { + match *self { + ProgressSender::Channel(ref c) => c.send(msg).map_err(|_| ()), + ProgressSender::Listener(ref b) => { + let action = match msg { + ProgressMsg::Payload(buf) => ResponseAction::DataAvailable(buf), + ProgressMsg::Done(status) => ResponseAction::ResponseComplete(status), + }; + b.invoke_with_listener(action); + Ok(()) + } + } + } +} + /// For use by loaders in responding to a Load message. -pub fn start_sending(start_chan: Sender<LoadResponse>, metadata: Metadata) -> Sender<ProgressMsg> { +pub fn start_sending(start_chan: LoadConsumer, metadata: Metadata) -> ProgressSender { start_sending_opt(start_chan, metadata).ok().unwrap() } /// For use by loaders in responding to a Load message that allows content sniffing. -pub fn start_sending_sniffed(start_chan: Sender<LoadResponse>, metadata: Metadata, +pub fn start_sending_sniffed(start_chan: LoadConsumer, metadata: Metadata, classifier: Arc<MIMEClassifier>, partial_body: &Vec<u8>) - -> Sender<ProgressMsg> { + -> ProgressSender { start_sending_sniffed_opt(start_chan, metadata, classifier, partial_body).ok().unwrap() } /// For use by loaders in responding to a Load message that allows content sniffing. -pub fn start_sending_sniffed_opt(start_chan: Sender<LoadResponse>, mut metadata: Metadata, +pub fn start_sending_sniffed_opt(start_chan: LoadConsumer, mut metadata: Metadata, classifier: Arc<MIMEClassifier>, partial_body: &Vec<u8>) - -> Result<Sender<ProgressMsg>, ()> { + -> Result<ProgressSender, ()> { if opts::get().sniff_mime_types { // TODO: should be calculated in the resource loader, from pull requeset #4094 let nosniff = false; @@ -94,15 +116,23 @@ pub fn start_sending_sniffed_opt(start_chan: Sender<LoadResponse>, mut metadata: } /// For use by loaders in responding to a Load message. -pub fn start_sending_opt(start_chan: Sender<LoadResponse>, metadata: Metadata) -> Result<Sender<ProgressMsg>, ()> { - let (progress_chan, progress_port) = channel(); - let result = start_chan.send(LoadResponse { - metadata: metadata, - progress_port: progress_port, - }); - match result { - Ok(_) => Ok(progress_chan), - Err(_) => Err(()) +pub fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata) -> Result<ProgressSender, ()> { + match start_chan { + LoadConsumer::Channel(start_chan) => { + let (progress_chan, progress_port) = channel(); + let result = start_chan.send(LoadResponse { + metadata: metadata, + progress_port: progress_port, + }); + match result { + Ok(_) => Ok(ProgressSender::Channel(progress_chan)), + Err(_) => Err(()) + } + } + LoadConsumer::Listener(target) => { + target.invoke_with_listener(ResponseAction::HeadersAvailable(metadata)); + Ok(ProgressSender::Listener(target)) + } } } @@ -176,8 +206,8 @@ impl ResourceManager { fn start(&mut self) { loop { match self.from_client.recv().unwrap() { - ControlMsg::Load(load_data) => { - self.load(load_data) + ControlMsg::Load(load_data, consumer) => { + self.load(load_data, consumer) } ControlMsg::SetCookiesForUrl(request, cookie_list, source) => { let header = Header::parse_header(&[cookie_list.into_bytes()]); @@ -199,7 +229,7 @@ impl ResourceManager { } } - fn load(&mut self, mut load_data: LoadData) { + fn load(&mut self, mut load_data: LoadData, consumer: LoadConsumer) { unsafe { if let Some(host_table) = HOST_TABLE { load_data = replace_hosts(load_data, host_table); @@ -208,10 +238,10 @@ impl ResourceManager { self.user_agent.as_ref().map(|ua| load_data.headers.set(UserAgent(ua.clone()))); - fn from_factory(factory: fn(LoadData, Arc<MIMEClassifier>)) - -> Box<Invoke<(LoadData, Arc<MIMEClassifier>)> + Send> { - box move |(load_data, classifier)| { - factory(load_data, classifier) + fn from_factory(factory: fn(LoadData, LoadConsumer, Arc<MIMEClassifier>)) + -> Box<Invoke<(LoadData, LoadConsumer, Arc<MIMEClassifier>)> + Send> { + box move |(load_data, senders, classifier)| { + factory(load_data, senders, classifier) } } @@ -222,13 +252,13 @@ impl ResourceManager { "about" => from_factory(about_loader::factory), _ => { debug!("resource_task: no loader for scheme {}", load_data.url.scheme); - start_sending(load_data.consumer, Metadata::default(load_data.url)) + start_sending(consumer, Metadata::default(load_data.url)) .send(ProgressMsg::Done(Err("no loader for scheme".to_string()))).unwrap(); return } }; debug!("resource_task: loading url: {}", load_data.url.serialize()); - loader.invoke((load_data, self.mime_classifier.clone())); + loader.invoke((load_data, consumer, self.mime_classifier.clone())); } } diff --git a/components/net_traits/image_cache_task.rs b/components/net_traits/image_cache_task.rs index 852b4ad9c71..905a7de3611 100644 --- a/components/net_traits/image_cache_task.rs +++ b/components/net_traits/image_cache_task.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use image::base::Image; +use LoadConsumer::Channel; use {ControlMsg, LoadData, ProgressMsg, ResourceTask}; use url::Url; @@ -84,7 +85,7 @@ impl ImageCacheTaskClient for ImageCacheTask { pub fn load_image_data(url: Url, resource_task: ResourceTask, placeholder: &[u8]) -> Result<Vec<u8>, ()> { let (response_chan, response_port) = channel(); - resource_task.send(ControlMsg::Load(LoadData::new(url.clone(), response_chan))).unwrap(); + resource_task.send(ControlMsg::Load(LoadData::new(url.clone()), Channel(response_chan))).unwrap(); let mut image_data = vec!(); diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 8a35fc87762..d73e3563194 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -51,11 +51,10 @@ pub struct LoadData { pub preserved_headers: Headers, pub data: Option<Vec<u8>>, pub cors: Option<ResourceCORSData>, - pub consumer: Sender<LoadResponse>, } impl LoadData { - pub fn new(url: Url, consumer: Sender<LoadResponse>) -> LoadData { + pub fn new(url: Url) -> LoadData { LoadData { url: url, method: Method::Get, @@ -63,17 +62,62 @@ impl LoadData { preserved_headers: Headers::new(), data: None, cors: None, - consumer: consumer, } } } +/// A listener for asynchronous network events. Cancelling the underlying request is unsupported. +pub trait AsyncResponseListener { + /// The response headers for a request have been received. + fn headers_available(&self, metadata: Metadata); + /// A portion of the response body has been received. This data is unavailable after + /// this method returned, and must be stored accordingly. + fn data_available(&self, payload: Vec<u8>); + /// The response is complete. If the provided status is an Err value, there is no guarantee + /// that the response body was completely read. + fn response_complete(&self, status: Result<(), String>); +} + +/// Data for passing between threads/processes to indicate a particular action to +/// take on a provided network listener. +pub enum ResponseAction { + /// Invoke headers_available + HeadersAvailable(Metadata), + /// Invoke data_available + DataAvailable(Vec<u8>), + /// Invoke response_complete + ResponseComplete(Result<(), String>) +} + +impl ResponseAction { + /// Execute the default action on a provided listener. + pub fn process(self, listener: &AsyncResponseListener) { + match self { + ResponseAction::HeadersAvailable(m) => listener.headers_available(m), + ResponseAction::DataAvailable(d) => listener.data_available(d), + ResponseAction::ResponseComplete(r) => listener.response_complete(r), + } + } +} + +/// A target for async networking events. Commonly used to dispatch a runnable event to another +/// thread storing the wrapped closure for later execution. +pub trait AsyncResponseTarget { + fn invoke_with_listener(&self, action: ResponseAction); +} + +/// A wrapper for a network load that can either be channel or event-based. +pub enum LoadConsumer { + Channel(Sender<LoadResponse>), + Listener(Box<AsyncResponseTarget + Send>), +} + /// Handle to a resource task pub type ResourceTask = Sender<ControlMsg>; pub enum ControlMsg { /// Request the data associated with a particular URL - Load(LoadData), + Load(LoadData, LoadConsumer), /// Store a set of cookies for a given originating URL SetCookiesForUrl(Url, String, CookieSource), /// Retrieve the stored cookies for a given URL @@ -172,7 +216,7 @@ pub enum ProgressMsg { pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) -> Result<(Metadata, Vec<u8>), String> { let (start_chan, start_port) = channel(); - resource_task.send(ControlMsg::Load(LoadData::new(url, start_chan))).unwrap(); + resource_task.send(ControlMsg::Load(LoadData::new(url), LoadConsumer::Channel(start_chan))).unwrap(); let response = start_port.recv().unwrap(); let mut buf = vec!(); @@ -188,7 +232,7 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url) /// Load a URL asynchronously and iterate over chunks of bytes from the response. pub fn load_bytes_iter(resource_task: &ResourceTask, url: Url) -> (Metadata, ProgressMsgPortIterator) { let (input_chan, input_port) = channel(); - resource_task.send(ControlMsg::Load(LoadData::new(url, input_chan))).unwrap(); + resource_task.send(ControlMsg::Load(LoadData::new(url), LoadConsumer::Channel(input_chan))).unwrap(); let response = input_port.recv().unwrap(); let iter = ProgressMsgPortIterator { progress_port: response.progress_port }; diff --git a/components/script/cors.rs b/components/script/cors.rs index e9521296464..235ec43f779 100644 --- a/components/script/cors.rs +++ b/components/script/cors.rs @@ -9,7 +9,14 @@ //! This library will eventually become the core of the Fetch crate //! with CORSRequest being expanded into FetchRequest (etc) +use network_listener::{NetworkListener, PreInvoke}; +use script_task::ScriptChan; +use net_traits::{AsyncResponseTarget, AsyncResponseListener, ResponseAction, Metadata}; + use std::ascii::AsciiExt; +use std::borrow::ToOwned; +use std::cell::RefCell; +use std::sync::{Arc, Mutex}; use time; use time::{now, Timespec}; @@ -24,6 +31,13 @@ use hyper::method::Method; use hyper::status::StatusClass::Success; use url::{SchemeData, Url}; +use util::task::spawn_named; + +/// Interface for network listeners concerned with CORS checks. Proper network requests +/// should be initiated from this method, based on the response provided. +pub trait AsyncCORSResponseListener { + fn response_available(&self, response: CORSResponse); +} #[derive(Clone)] pub struct CORSRequest { @@ -88,7 +102,52 @@ impl CORSRequest { } } - /// https://fetch.spec.whatwg.org/#concept-http-fetch + pub fn http_fetch_async(&self, + listener: Box<AsyncCORSResponseListener+Send>, + script_chan: Box<ScriptChan+Send>) { + struct CORSContext { + listener: Box<AsyncCORSResponseListener+Send>, + response: RefCell<Option<CORSResponse>>, + } + + // This is shoe-horning the CORSReponse stuff into the rest of the async network + // framework right now. It would be worth redesigning http_fetch to do this properly. + impl AsyncResponseListener for CORSContext { + fn headers_available(&self, _metadata: Metadata) { + } + + fn data_available(&self, _payload: Vec<u8>) { + } + + fn response_complete(&self, _status: Result<(), String>) { + let response = self.response.borrow_mut().take().unwrap(); + self.listener.response_available(response); + } + } + impl PreInvoke for CORSContext {} + + let context = CORSContext { + listener: listener, + response: RefCell::new(None), + }; + let listener = NetworkListener { + context: Arc::new(Mutex::new(context)), + script_chan: script_chan, + }; + + // TODO: this exists only to make preflight check non-blocking + // perhaps should be handled by the resource task? + let req = self.clone(); + spawn_named("cors".to_owned(), move || { + let response = req.http_fetch(); + let mut context = listener.context.lock(); + let context = context.as_mut().unwrap(); + *context.response.borrow_mut() = Some(response); + listener.invoke_with_listener(ResponseAction::ResponseComplete(Ok(()))); + }); + } + + /// http://fetch.spec.whatwg.org/#concept-http-fetch /// This method assumes that the CORS flag is set /// This does not perform the full HTTP fetch, rather it handles part of the CORS filtering /// if self.mode is ForcedPreflight, then the CORS-with-forced-preflight diff --git a/components/script/dom/activation.rs b/components/script/dom/activation.rs index a643559034b..34bd440527c 100644 --- a/components/script/dom/activation.rs +++ b/components/script/dom/activation.rs @@ -20,19 +20,19 @@ pub trait Activatable : Copy { // Is this particular instance of the element activatable? fn is_instance_activatable(&self) -> bool; - // https://html.spec.whatwg.org/multipage/interaction.html#run-pre-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps fn pre_click_activation(&self); - // https://html.spec.whatwg.org/multipage/interaction.html#run-canceled-activation-steps + // https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps fn canceled_activation(&self); - // https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps fn activation_behavior(&self, event: JSRef<Event>, target: JSRef<EventTarget>); // https://html.spec.whatwg.org/multipage/#implicit-submission fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool); - // https://html.spec.whatwg.org/multipage/interaction.html#run-synthetic-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps fn synthetic_click_activation(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) { let element = self.as_element().root(); // Step 1 diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index cdc472d6e3f..55ad525bba3 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -16,7 +16,7 @@ use dom::window::Window; use dom::virtualmethods::vtable_for; use devtools_traits::AttrInfo; -use util::str::{DOMString, split_html_space_chars}; +use util::str::{DOMString, parse_unsigned_integer, split_html_space_chars}; use string_cache::{Atom, Namespace}; @@ -55,8 +55,7 @@ impl AttrValue { } pub fn from_u32(string: DOMString, default: u32) -> AttrValue { - // XXX Is parse() correct? - let result: u32 = string.parse().unwrap_or(default); + let result = parse_unsigned_integer(string.chars()).unwrap_or(default); AttrValue::UInt(string, result) } diff --git a/components/script/dom/bindings/cell.rs b/components/script/dom/bindings/cell.rs index b64d80cefc3..177fed9397b 100644 --- a/components/script/dom/bindings/cell.rs +++ b/components/script/dom/bindings/cell.rs @@ -16,6 +16,7 @@ use std::cell::{BorrowState, RefCell, Ref, RefMut}; /// /// This extends the API of `core::cell::RefCell` to allow unsafe access in /// certain situations, with dynamic checking in debug builds. +#[derive(Clone)] pub struct DOMRefCell<T> { value: RefCell<T>, } diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 233143851e6..3c3df454ca1 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -12,8 +12,8 @@ use dom::bindings::js::{JS, JSRef, Root, Unrooted}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::window::{self, WindowHelpers}; -use script_task::ScriptChan; use devtools_traits::DevtoolsControlChan; +use script_task::{ScriptChan, ScriptPort, ScriptMsg, ScriptTask}; use msg::constellation_msg::{PipelineId, WorkerId}; use net_traits::ResourceTask; @@ -129,6 +129,25 @@ impl<'a> GlobalRef<'a> { GlobalRef::Worker(ref worker) => worker.script_chan(), } } + + /// Create a new sender/receiver pair that can be used to implement an on-demand + /// event loop. Used for implementing web APIs that require blocking semantics + /// without resorting to nested event loops. + pub fn new_script_pair(&self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) { + match *self { + GlobalRef::Window(ref window) => window.new_script_pair(), + GlobalRef::Worker(ref worker) => worker.new_script_pair(), + } + } + + /// Process a single event as if it were the next event in the task queue for + /// this global. + pub fn process_event(&self, msg: ScriptMsg) { + match *self { + GlobalRef::Window(_) => ScriptTask::process_event(msg), + GlobalRef::Worker(ref worker) => worker.process_event(msg), + } + } } impl<'a> Reflectable for GlobalRef<'a> { diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 1695f16ead7..3d32abb610a 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -207,6 +207,16 @@ impl<T: JSTraceable> JSTraceable for Option<T> { } } +impl<T: JSTraceable, U: JSTraceable> JSTraceable for Result<T, U> { + #[inline] + fn trace(&self, trc: *mut JSTracer) { + match *self { + Ok(ref inner) => inner.trace(trc), + Err(ref inner) => inner.trace(trc), + } + } +} + impl<K,V,S> JSTraceable for HashMap<K, V, S> where K: Hash + Eq + JSTraceable, V: JSTraceable, @@ -297,6 +307,12 @@ impl JSTraceable for Box<LayoutRPC+'static> { } } +impl JSTraceable for () { + #[inline] + fn trace(&self, _trc: *mut JSTracer) { + } +} + /// Holds a set of vectors that need to be rooted pub struct RootedCollectionSet { set: Vec<HashSet<*const RootedVec<()>>> diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 7ac2fac20d3..5c89b58f276 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -27,7 +27,8 @@ use geom::point::Point2D; use geom::rect::Rect; use geom::size::Size2D; -use canvas::canvas_paint_task::{CanvasMsg, CanvasPaintTask, FillOrStrokeStyle}; +use canvas::canvas_msg::{CanvasMsg, Canvas2dMsg, CanvasCommonMsg}; +use canvas::canvas_paint_task::{CanvasPaintTask, FillOrStrokeStyle}; use canvas::canvas_paint_task::{LinearGradientStyle, RadialGradientStyle}; use canvas::canvas_paint_task::{LineCapStyle, LineJoinStyle}; @@ -36,7 +37,7 @@ use net_traits::image_cache_task::{ImageResponseMsg, Msg}; use png::PixelsByColorType; use std::borrow::ToOwned; -use std::cell::Cell; +use std::cell::RefCell; use std::num::{Float, ToPrimitive}; use std::sync::{Arc}; use std::sync::mpsc::{channel, Sender}; @@ -52,40 +53,56 @@ pub struct CanvasRenderingContext2D { global: GlobalField, renderer: Sender<CanvasMsg>, canvas: JS<HTMLCanvasElement>, - global_alpha: Cell<f64>, - image_smoothing_enabled: Cell<bool>, - stroke_color: Cell<RGBA>, - line_width: Cell<f64>, - line_cap: Cell<LineCapStyle>, - line_join: Cell<LineJoinStyle>, - miter_limit: Cell<f64>, - fill_color: Cell<RGBA>, - transform: Cell<Matrix2D<f32>>, + state: RefCell<CanvasContextState>, + saved_states: RefCell<Vec<CanvasContextState>>, } -impl CanvasRenderingContext2D { - fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) - -> CanvasRenderingContext2D { +#[derive(Clone)] +#[jstraceable] +struct CanvasContextState { + global_alpha: f64, + image_smoothing_enabled: bool, + stroke_color: RGBA, + line_width: f64, + line_cap: LineCapStyle, + line_join: LineJoinStyle, + miter_limit: f64, + fill_color: RGBA, + transform: Matrix2D<f32>, +} + +impl CanvasContextState { + fn new() -> CanvasContextState { let black = RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0, }; + CanvasContextState { + global_alpha: 1.0, + image_smoothing_enabled: true, + stroke_color: black, + line_width: 1.0, + line_cap: LineCapStyle::Butt, + line_join: LineJoinStyle::Miter, + miter_limit: 10.0, + fill_color: black, + transform: Matrix2D::identity(), + } + } +} + +impl CanvasRenderingContext2D { + fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) + -> CanvasRenderingContext2D { CanvasRenderingContext2D { reflector_: Reflector::new(), global: GlobalField::from_rooted(&global), renderer: CanvasPaintTask::start(size), canvas: JS::from_rooted(canvas), - global_alpha: Cell::new(1.0), - image_smoothing_enabled: Cell::new(true), - stroke_color: Cell::new(black), - line_width: Cell::new(1.0), - line_cap: Cell::new(LineCapStyle::Butt), - line_join: Cell::new(LineJoinStyle::Miter), - miter_limit: Cell::new(10.0), - fill_color: Cell::new(black), - transform: Cell::new(Matrix2D::identity()), + state: RefCell::new(CanvasContextState::new()), + saved_states: RefCell::new(Vec::new()), } } @@ -96,11 +113,11 @@ impl CanvasRenderingContext2D { } pub fn recreate(&self, size: Size2D<i32>) { - self.renderer.send(CanvasMsg::Recreate(size)).unwrap(); + self.renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap(); } fn update_transform(&self) { - self.renderer.send(CanvasMsg::SetTransform(self.transform.get())).unwrap() + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetTransform(self.state.borrow().transform))).unwrap() } // It is used by DrawImage to calculate the size of the source and destination rectangles based @@ -184,20 +201,20 @@ impl CanvasRenderingContext2D { return Err(IndexSize) } - let smoothing_enabled = self.image_smoothing_enabled.get(); + let smoothing_enabled = self.state.borrow().image_smoothing_enabled; // If the source and target canvas are the same let msg = if self.canvas.root().r() == canvas { - CanvasMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled) + CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled)) } else { // Source and target canvases are different let context = canvas.get_2d_context().root(); let renderer = context.r().get_renderer(); let (sender, receiver) = channel::<Vec<u8>>(); // Reads pixels from source image - renderer.send(CanvasMsg::GetImageData(source_rect, image_size, sender)).unwrap(); + renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(source_rect, image_size, sender))).unwrap(); let imagedata = receiver.recv().unwrap(); // Writes pixels to destination canvas - CanvasMsg::DrawImage(imagedata, source_rect.size, dest_rect, source_rect, smoothing_enabled) + CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage(imagedata, source_rect.size, dest_rect, source_rect, smoothing_enabled)) }; self.renderer.send(msg).unwrap(); @@ -216,10 +233,10 @@ impl CanvasRenderingContext2D { return Err(IndexSize) } - let smoothing_enabled = self.image_smoothing_enabled.get(); - self.renderer.send(CanvasMsg::DrawImage( + let smoothing_enabled = self.state.borrow().image_smoothing_enabled; + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::DrawImage( image_data, image_size, dest_rect, - source_rect, smoothing_enabled)).unwrap(); + source_rect, smoothing_enabled))).unwrap(); Ok(()) } @@ -318,13 +335,29 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> Temporary::new(self.canvas) } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-save + fn Save(self) { + self.saved_states.borrow_mut().push(self.state.borrow().clone()); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap(); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore + fn Restore(self) { + let mut saved_states = self.saved_states.borrow_mut(); + if let Some(state) = saved_states.pop() { + self.state.borrow_mut().clone_from(&state); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::RestoreContext)).unwrap(); + } + } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale fn Scale(self, x: f64, y: f64) { if !(x.is_finite() && y.is_finite()) { return; } - self.transform.set(self.transform.get().scale(x as f32, y as f32)); + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.scale(x as f32, y as f32); self.update_transform() } @@ -334,7 +367,8 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.transform.set(self.transform.get().translate(x as f32, y as f32)); + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.translate(x as f32, y as f32); self.update_transform() } @@ -345,12 +379,13 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.transform.set(self.transform.get().mul(&Matrix2D::new(a as f32, - b as f32, - c as f32, - d as f32, - e as f32, - f as f32))); + let transform = self.state.borrow().transform; + self.state.borrow_mut().transform = transform.mul(&Matrix2D::new(a as f32, + b as f32, + c as f32, + d as f32, + e as f32, + f as f32)); self.update_transform() } @@ -361,18 +396,19 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.transform.set(Matrix2D::new(a as f32, - b as f32, - c as f32, - d as f32, - e as f32, - f as f32)); + self.state.borrow_mut().transform = Matrix2D::new(a as f32, + b as f32, + c as f32, + d as f32, + e as f32, + f as f32); self.update_transform() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha fn GlobalAlpha(self) -> f64 { - self.global_alpha.get() + let state = self.state.borrow(); + state.global_alpha } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha @@ -381,49 +417,49 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.global_alpha.set(alpha); - self.renderer.send(CanvasMsg::SetGlobalAlpha(alpha as f32)).unwrap() + self.state.borrow_mut().global_alpha = alpha; + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetGlobalAlpha(alpha as f32))).unwrap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect fn FillRect(self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.renderer.send(CanvasMsg::FillRect(rect)).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap(); } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.renderer.send(CanvasMsg::ClearRect(rect)).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClearRect(rect))).unwrap(); } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.renderer.send(CanvasMsg::StrokeRect(rect)).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::StrokeRect(rect))).unwrap(); } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath fn BeginPath(self) { - self.renderer.send(CanvasMsg::BeginPath).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath fn ClosePath(self) { - self.renderer.send(CanvasMsg::ClosePath).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClosePath)).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill fn Fill(self, _: CanvasWindingRule) { - self.renderer.send(CanvasMsg::Fill).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke fn Stroke(self) { - self.renderer.send(CanvasMsg::Stroke).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Stroke)).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage @@ -592,7 +628,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.renderer.send(CanvasMsg::MoveTo(Point2D(x as f32, y as f32))).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::MoveTo(Point2D(x as f32, y as f32)))).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto @@ -601,7 +637,16 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.renderer.send(CanvasMsg::LineTo(Point2D(x as f32, y as f32))).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::LineTo(Point2D(x as f32, y as f32)))).unwrap(); + } + + // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect + fn Rect(self, x: f64, y: f64, width: f64, height: f64) { + if [x, y, width, height].iter().all(|val| val.is_finite()) { + let rect = Rect(Point2D(x as f32, y as f32), + Size2D(width as f32, height as f32)); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Rect(rect))).unwrap(); + } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto @@ -611,8 +656,8 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.renderer.send(CanvasMsg::QuadraticCurveTo(Point2D(cpx as f32, cpy as f32), - Point2D(x as f32, y as f32))).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::QuadraticCurveTo(Point2D(cpx as f32, cpy as f32), + Point2D(x as f32, y as f32)))).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto @@ -622,9 +667,9 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.renderer.send(CanvasMsg::BezierCurveTo(Point2D(cp1x as f32, cp1y as f32), - Point2D(cp2x as f32, cp2y as f32), - Point2D(x as f32, y as f32))).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BezierCurveTo(Point2D(cp1x as f32, cp1y as f32), + Point2D(cp2x as f32, cp2y as f32), + Point2D(x as f32, y as f32)))).unwrap(); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc @@ -640,8 +685,8 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return Err(IndexSize); } - self.renderer.send(CanvasMsg::Arc(Point2D(x as f32, y as f32), r as f32, - start as f32, end as f32, ccw)).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Arc(Point2D(x as f32, y as f32), r as f32, + start as f32, end as f32, ccw))).unwrap(); Ok(()) } @@ -653,20 +698,21 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> if r < 0.0 { return Err(IndexSize); } - self.renderer.send(CanvasMsg::ArcTo(Point2D(cp1x as f32, cp1y as f32), - Point2D(cp2x as f32, cp2y as f32), - r as f32)).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ArcTo(Point2D(cp1x as f32, cp1y as f32), + Point2D(cp2x as f32, cp2y as f32), + r as f32))).unwrap(); Ok(()) } // https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled fn ImageSmoothingEnabled(self) -> bool { - self.image_smoothing_enabled.get() + let state = self.state.borrow(); + state.image_smoothing_enabled } // https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled fn SetImageSmoothingEnabled(self, value: bool) -> () { - self.image_smoothing_enabled.set(value); + self.state.borrow_mut().image_smoothing_enabled = value; } // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle @@ -675,7 +721,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> // // https://html.spec.whatwg.org/multipage/#serialisation-of-a-colour let mut result = String::new(); - self.stroke_color.get().to_css(&mut result).unwrap(); + self.state.borrow().stroke_color.to_css(&mut result).unwrap(); StringOrCanvasGradientOrCanvasPattern::eString(result) } @@ -685,9 +731,9 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> StringOrCanvasGradientOrCanvasPattern::eString(string) => { match parse_color(&string) { Ok(rgba) => { - self.stroke_color.set(rgba); + self.state.borrow_mut().stroke_color = rgba; self.renderer - .send(CanvasMsg::SetStrokeStyle(FillOrStrokeStyle::Color(rgba))) + .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetStrokeStyle(FillOrStrokeStyle::Color(rgba)))) .unwrap(); } _ => {} @@ -705,7 +751,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> // // https://html.spec.whatwg.org/multipage/#serialisation-of-a-colour let mut result = String::new(); - self.stroke_color.get().to_css(&mut result).unwrap(); + self.state.borrow().stroke_color.to_css(&mut result).unwrap(); StringOrCanvasGradientOrCanvasPattern::eString(result) } @@ -715,16 +761,16 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> StringOrCanvasGradientOrCanvasPattern::eString(string) => { match parse_color(&string) { Ok(rgba) => { - self.fill_color.set(rgba); + self.state.borrow_mut().fill_color = rgba; self.renderer - .send(CanvasMsg::SetFillStyle(FillOrStrokeStyle::Color(rgba))) + .send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle(FillOrStrokeStyle::Color(rgba)))) .unwrap() } _ => {} } } StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => { - self.renderer.send(CanvasMsg::SetFillStyle(gradient.root().r().to_fill_or_stroke_style())).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle(gradient.root().r().to_fill_or_stroke_style()))).unwrap(); } _ => {} } @@ -763,7 +809,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> let dest_rect = Rect(Point2D(sx as f64, sy as f64), Size2D(sw as f64, sh as f64)); let canvas_size = self.canvas.root().r().get_size(); let canvas_size = Size2D(canvas_size.width as f64, canvas_size.height as f64); - self.renderer.send(CanvasMsg::GetImageData(dest_rect, canvas_size, sender)).unwrap(); + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender))).unwrap(); let data = receiver.recv().unwrap(); Ok(ImageData::new(self.global.root().r(), sw.abs().to_u32().unwrap(), sh.abs().to_u32().unwrap(), Some(data))) } @@ -784,7 +830,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> let image_data_size = Size2D(image_data_size.width as f64, image_data_size.height as f64); let image_data_rect = Rect(Point2D(dx, dy), image_data_size); let dirty_rect = None; - self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect)).unwrap() + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data, image_data_rect, dirty_rect))).unwrap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata @@ -809,7 +855,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> imagedata.Height() as f64)); let dirty_rect = Some(Rect(Point2D(dirtyX, dirtyY), Size2D(dirtyWidth, dirtyHeight))); - self.renderer.send(CanvasMsg::PutImageData(data, image_data_rect, dirty_rect)).unwrap() + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data, image_data_rect, dirty_rect))).unwrap() } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient @@ -846,7 +892,8 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth fn LineWidth(self) -> f64 { - self.line_width.get() + let state = self.state.borrow(); + state.line_width } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth @@ -855,43 +902,50 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.line_width.set(width); - self.renderer.send(CanvasMsg::SetLineWidth(width as f32)).unwrap() + self.state.borrow_mut().line_width = width; + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineWidth(width as f32))).unwrap() } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn LineCap(self) -> DOMString { - match self.line_cap.get() { + let state = self.state.borrow(); + match state.line_cap { LineCapStyle::Butt => "butt".to_owned(), LineCapStyle::Round => "round".to_owned(), LineCapStyle::Square => "square".to_owned(), } } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap fn SetLineCap(self, cap_str: DOMString) { if let Some(cap) = LineCapStyle::from_str(&cap_str) { - self.line_cap.set(cap); - self.renderer.send(CanvasMsg::SetLineCap(cap)).unwrap() + self.state.borrow_mut().line_cap = cap; + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineCap(cap))).unwrap() } } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn LineJoin(self) -> DOMString { - match self.line_join.get() { + let state = self.state.borrow(); + match state.line_join { LineJoinStyle::Round => "round".to_owned(), LineJoinStyle::Bevel => "bevel".to_owned(), LineJoinStyle::Miter => "miter".to_owned(), } } + // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin fn SetLineJoin(self, join_str: DOMString) { if let Some(join) = LineJoinStyle::from_str(&join_str) { - self.line_join.set(join); - self.renderer.send(CanvasMsg::SetLineJoin(join)).unwrap() + self.state.borrow_mut().line_join = join; + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineJoin(join))).unwrap() } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit fn MiterLimit(self) -> f64 { - self.miter_limit.get() + let state = self.state.borrow(); + state.miter_limit } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit @@ -900,15 +954,15 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> return; } - self.miter_limit.set(limit); - self.renderer.send(CanvasMsg::SetMiterLimit(limit as f32)).unwrap() + self.state.borrow_mut().miter_limit = limit; + self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetMiterLimit(limit as f32))).unwrap() } } #[unsafe_destructor] impl Drop for CanvasRenderingContext2D { fn drop(&mut self) { - self.renderer.send(CanvasMsg::Close).unwrap(); + self.renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)).unwrap(); } } diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index bc1106f94cc..4f10e7d39f4 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -8,6 +8,7 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, ElementCast}; use dom::bindings::codegen::InheritTypes::NodeCast; +use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::error::Error::IndexSize; use dom::bindings::js::{JSRef, LayoutJS, Temporary}; @@ -118,6 +119,21 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { Ok(()) } + // https://dom.spec.whatwg.org/#dom-childnode-before + fn Before(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).before(nodes) + } + + // https://dom.spec.whatwg.org/#dom-childnode-after + fn After(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).after(nodes) + } + + // https://dom.spec.whatwg.org/#dom-childnode-replacewith + fn ReplaceWith(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).replace_with(nodes) + } + // https://dom.spec.whatwg.org/#dom-childnode-remove fn Remove(self) { let node: JSRef<Node> = NodeCast::from_ref(self); diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 83168d44e2d..8ab0621e0f9 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -21,7 +21,7 @@ use dom::messageevent::MessageEvent; use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler, WorkerErrorHandler}; use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::workerglobalscope::WorkerGlobalScopeTypeId; -use script_task::{ScriptTask, ScriptChan, ScriptMsg, TimerSource}; +use script_task::{ScriptTask, ScriptChan, ScriptMsg, TimerSource, ScriptPort}; use script_task::StackRootTLS; use msg::constellation_msg::PipelineId; @@ -38,7 +38,7 @@ use js::jsval::JSVal; use js::rust::Cx; use std::rc::Rc; -use std::sync::mpsc::{Sender, Receiver}; +use std::sync::mpsc::{Sender, Receiver, channel}; use url::Url; /// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with @@ -198,6 +198,8 @@ impl DedicatedWorkerGlobalScope { pub trait DedicatedWorkerGlobalScopeHelpers { fn script_chan(self) -> Box<ScriptChan+Send>; fn pipeline(self) -> PipelineId; + fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>); + fn process_event(self, msg: ScriptMsg); } impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> { @@ -213,6 +215,19 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalSc fn pipeline(self) -> PipelineId { self.id } + + fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) { + let (tx, rx) = channel(); + let chan = box SendableWorkerScriptChan { + sender: tx, + worker: self.worker.borrow().as_ref().unwrap().clone(), + }; + (chan, box rx) + } + + fn process_event(self, msg: ScriptMsg) { + self.handle_event(msg); + } } trait PrivateDedicatedWorkerGlobalScopeHelpers { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index bff8ea0cdba..aa360edd3a3 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -19,6 +19,7 @@ use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLAppletE use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLEmbedElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLFormElementDerived, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, CharacterDataCast}; +use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{NotSupported, InvalidCharacter, Security}; use dom::bindings::error::Error::HierarchyRequest; @@ -63,7 +64,7 @@ use dom::window::{Window, WindowHelpers, ReflowReason}; use layout_interface::{HitTestResponse, MouseOverResponse}; use msg::compositor_msg::ScriptListener; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::{ConstellationChan, Key, KeyState, KeyModifiers, MozBrowserEvent}; +use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyModifiers, MozBrowserEvent}; use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL}; use net_traits::CookieSource::NonHTTP; use net_traits::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl}; @@ -215,7 +216,7 @@ pub trait DocumentHelpers<'a> { fn is_scripting_enabled(self) -> bool; fn begin_focus_transaction(self); fn request_focus(self, elem: JSRef<Element>); - fn commit_focus_transaction(self); + fn commit_focus_transaction(self, focus_type: FocusType); fn title_changed(self); fn send_title_to_compositor(self); fn dirty_all_nodes(self); @@ -223,12 +224,14 @@ pub trait DocumentHelpers<'a> { button: MouseButton, point: Point2D<f32>); fn dispatch_key_event(self, key: Key, state: KeyState, modifiers: KeyModifiers, compositor: &mut Box<ScriptListener+'static>); + fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>) + -> Fallible<Temporary<Node>>; /// Handles a mouse-move event coming from the compositor. fn handle_mouse_move_event(self, js_runtime: *mut JSRuntime, point: Point2D<f32>, - prev_mouse_over_targets: &mut Vec<JS<Node>>); + prev_mouse_over_targets: &mut RootedVec<JS<Node>>); fn set_current_script(self, script: Option<JSRef<HTMLScriptElement>>); fn trigger_mozbrowser_event(self, event: MozBrowserEvent); @@ -457,7 +460,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { /// Reassign the focus context to the element that last requested focus during this /// transaction, or none if no elements requested it. - fn commit_focus_transaction(self) { + fn commit_focus_transaction(self, focus_type: FocusType) { //TODO: dispatch blur, focus, focusout, and focusin events if let Some(ref elem) = self.focused.get().root() { @@ -470,9 +473,16 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { if let Some(ref elem) = self.focused.get().root() { let node: JSRef<Node> = NodeCast::from_ref(elem.r()); node.set_focus_state(true); + + // Update the focus state for all elements in the focus chain. + // https://html.spec.whatwg.org/multipage/#focus-chain + if focus_type == FocusType::Element { + let window = self.window.root(); + let ConstellationChan(ref chan) = window.r().constellation_chan(); + let event = ConstellationMsg::FocusMsg(window.r().pipeline()); + chan.send(event).unwrap(); + } } - // TODO: Update the focus state for all elements in the focus chain. - // https://html.spec.whatwg.org/multipage/interaction.html#focus-chain } /// Handles any updates when the document's title has changed. @@ -549,27 +559,28 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events event.set_trusted(true); - // https://html.spec.whatwg.org/multipage/interaction.html#run-authentic-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps el.r().authentic_click_activation(event); - self.commit_focus_transaction(); + self.commit_focus_transaction(FocusType::Element); window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent); } fn handle_mouse_move_event(self, js_runtime: *mut JSRuntime, point: Point2D<f32>, - prev_mouse_over_targets: &mut Vec<JS<Node>>) { + prev_mouse_over_targets: &mut RootedVec<JS<Node>>) { // Build a list of elements that are currently under the mouse. let mouse_over_addresses = self.get_nodes_under_mouse(&point); - let mouse_over_targets: Vec<JS<Node>> = mouse_over_addresses.iter() - .filter_map(|node_address| { + let mut mouse_over_targets: RootedVec<JS<Node>> = RootedVec::new(); + for node_address in mouse_over_addresses.iter() { let node = node::from_untrusted_node_address(js_runtime, *node_address); - node.root().r().inclusive_ancestors() - .map(|node| node.root()) - .find(|node| node.r().is_element()) - .map(|node| JS::from_rooted(node.r())) - }).collect(); + mouse_over_targets.push(node.root().r().inclusive_ancestors() + .map(|node| node.root()) + .find(|node| node.r() + .is_element()) + .map(|node| JS::from_rooted(node.r())).unwrap()); + }; // Remove hover from any elements in the previous list that are no longer // under the mouse. @@ -616,7 +627,8 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { } // Store the current mouse over targets for next frame - *prev_mouse_over_targets = mouse_over_targets; + prev_mouse_over_targets.clear(); + prev_mouse_over_targets.append(&mut *mouse_over_targets); let window = self.window.root(); window.r().reflow(ReflowGoal::ForDisplay, @@ -702,6 +714,34 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> { window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::KeyEvent); } + fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>) + -> Fallible<Temporary<Node>> { + if nodes.len() == 1 { + match nodes.into_iter().next().unwrap() { + NodeOrString::eNode(node) => Ok(Temporary::from_unrooted(node)), + NodeOrString::eString(string) => { + Ok(NodeCast::from_temporary(self.CreateTextNode(string))) + }, + } + } else { + let fragment = NodeCast::from_temporary(self.CreateDocumentFragment()).root(); + for node in nodes.into_iter() { + match node { + NodeOrString::eNode(node) => { + try!(fragment.r().AppendChild(node.root().r())); + }, + NodeOrString::eString(string) => { + let node = NodeCast::from_temporary(self.CreateTextNode(string)).root(); + // No try!() here because appending a text node + // should not fail. + fragment.r().AppendChild(node.r()).unwrap(); + } + } + } + Ok(Temporary::from_rooted(fragment.r())) + } + } + fn set_current_script(self, script: Option<JSRef<HTMLScriptElement>>) { self.current_script.assign(script); } @@ -763,7 +803,7 @@ impl Document { implementation: Default::default(), location: Default::default(), content_type: match content_type { - Some(string) => string.clone(), + Some(string) => string, None => match is_html_document { // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument IsHTMLDocument::HTMLDocument => "text/html".to_owned(), @@ -877,7 +917,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { self.url().serialize() } - // https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement + // https://html.spec.whatwg.org/multipage/#dom-document-activeelement fn GetActiveElement(self) -> Option<Temporary<Element>> { // TODO: Step 2. @@ -1377,6 +1417,16 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { NodeCast::from_ref(self).child_elements().count() as u32 } + // https://dom.spec.whatwg.org/#dom-parentnode-prepend + fn Prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).prepend(nodes) + } + + // https://dom.spec.whatwg.org/#dom-parentnode-append + fn Append(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).append(nodes) + } + // https://dom.spec.whatwg.org/#dom-parentnode-queryselector fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { let root: JSRef<Node> = NodeCast::from_ref(self); diff --git a/components/script/dom/documentfragment.rs b/components/script/dom/documentfragment.rs index 43af033a0fb..51f7fa48571 100644 --- a/components/script/dom/documentfragment.rs +++ b/components/script/dom/documentfragment.rs @@ -7,8 +7,9 @@ use dom::bindings::codegen::Bindings::DocumentFragmentBinding::DocumentFragmentM use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::InheritTypes::DocumentFragmentDerived; use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast}; +use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::js::{JSRef, Temporary}; -use dom::bindings::error::Fallible; +use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::document::Document; use dom::element::Element; @@ -73,6 +74,16 @@ impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> { NodeCast::from_ref(self).child_elements().count() as u32 } + // https://dom.spec.whatwg.org/#dom-parentnode-prepend + fn Prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).prepend(nodes) + } + + // https://dom.spec.whatwg.org/#dom-parentnode-append + fn Append(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).append(nodes) + } + // https://dom.spec.whatwg.org/#dom-parentnode-queryselector fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { let root: JSRef<Node> = NodeCast::from_ref(self); diff --git a/components/script/dom/documenttype.rs b/components/script/dom/documenttype.rs index c8e3dfaa40e..b5fd4300b70 100644 --- a/components/script/dom/documenttype.rs +++ b/components/script/dom/documenttype.rs @@ -5,6 +5,8 @@ use dom::bindings::codegen::Bindings::DocumentTypeBinding; use dom::bindings::codegen::Bindings::DocumentTypeBinding::DocumentTypeMethods; use dom::bindings::codegen::InheritTypes::{DocumentTypeDerived, NodeCast}; +use dom::bindings::codegen::UnionTypes::NodeOrString; +use dom::bindings::error::ErrorResult; use dom::bindings::js::{JSRef, Temporary}; use dom::document::Document; use dom::eventtarget::{EventTarget, EventTargetTypeId}; @@ -87,6 +89,21 @@ impl<'a> DocumentTypeMethods for JSRef<'a, DocumentType> { self.system_id.clone() } + // https://dom.spec.whatwg.org/#dom-childnode-before + fn Before(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).before(nodes) + } + + // https://dom.spec.whatwg.org/#dom-childnode-after + fn After(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).after(nodes) + } + + // https://dom.spec.whatwg.org/#dom-childnode-replacewith + fn ReplaceWith(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).replace_with(nodes) + } + // https://dom.spec.whatwg.org/#dom-childnode-remove fn Remove(self) { let node: JSRef<Node> = NodeCast::from_ref(self); diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index efc5d5de1ac..f47651629e6 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -23,6 +23,7 @@ use dom::bindings::codegen::InheritTypes::{HTMLTableElementDerived, HTMLTableCel use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementDerived, HTMLTextAreaElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLTableSectionElementDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::HTMLAnchorElementCast; +use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{InvalidCharacter, Syntax}; use dom::bindings::error::Error::NoModificationAllowed; @@ -170,14 +171,14 @@ pub trait RawLayoutElementHelpers { #[inline] #[allow(unsafe_code)] -unsafe fn get_attr_for_layout<'a>(elem: &'a Element, namespace: &Namespace, name: &Atom) -> Option<&'a JS<Attr>> { +unsafe fn get_attr_for_layout(elem: &Element, namespace: &Namespace, name: &Atom) -> Option<LayoutJS<Attr>> { // cast to point to T in RefCell<T> directly let attrs = elem.attrs.borrow_for_layout(); attrs.iter().find(|attr: & &JS<Attr>| { let attr = attr.to_layout().unsafe_get(); *name == (*attr).local_name_atom_forever() && (*attr).namespace() == namespace - }) + }).map(|attr| attr.to_layout()) } #[allow(unsafe_code)] @@ -186,8 +187,7 @@ impl RawLayoutElementHelpers for Element { unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> { get_attr_for_layout(self, namespace, name).map(|attr| { - let attr = attr.to_layout().unsafe_get(); - (*attr).value_ref_forever() + (*attr.unsafe_get()).value_ref_forever() }) } @@ -207,40 +207,22 @@ impl RawLayoutElementHelpers for Element { #[inline] unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &Atom) -> Option<Atom> { - let attrs = self.attrs.borrow_for_layout(); - (*attrs).iter().find(|attr: & &JS<Attr>| { - let attr = attr.to_layout().unsafe_get(); - *name == (*attr).local_name_atom_forever() && - (*attr).namespace() == namespace - }).and_then(|attr| { - let attr = attr.to_layout().unsafe_get(); - (*attr).value_atom_forever() + get_attr_for_layout(self, namespace, name).and_then(|attr| { + (*attr.unsafe_get()).value_atom_forever() }) } #[inline] unsafe fn has_class_for_layout(&self, name: &Atom) -> bool { - let attrs = self.attrs.borrow_for_layout(); - (*attrs).iter().find(|attr: & &JS<Attr>| { - let attr = attr.to_layout().unsafe_get(); - (*attr).local_name_atom_forever() == atom!("class") - }).map_or(false, |attr| { - let attr = attr.to_layout().unsafe_get(); - (*attr).value_tokens_forever().map(|tokens| { - tokens.iter().any(|atom| atom == name) - }) - }.take().unwrap()) + get_attr_for_layout(self, &ns!(""), &atom!("class")).map_or(false, |attr| { + (*attr.unsafe_get()).value_tokens_forever().unwrap().iter().any(|atom| atom == name) + }) } #[inline] unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]> { - let attrs = self.attrs.borrow_for_layout(); - (*attrs).iter().find(|attr: & &JS<Attr>| { - let attr = attr.to_layout().unsafe_get(); - (*attr).local_name_atom_forever() == atom!("class") - }).and_then(|attr| { - let attr = attr.to_layout().unsafe_get(); - (*attr).value_tokens_forever() + get_attr_for_layout(self, &ns!(""), &atom!("class")).map(|attr| { + (*attr.unsafe_get()).value_tokens_forever().unwrap() }) } @@ -440,6 +422,7 @@ pub trait ElementHelpers<'a> { fn get_important_inline_style_declaration(self, property: &Atom) -> Option<PropertyDeclaration>; fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString>; fn get_root_element(self) -> Option<Temporary<Element>>; + fn lookup_prefix(self, namespace: Option<DOMString>) -> Option<DOMString>; } impl<'a> ElementHelpers<'a> for JSRef<'a, Element> { @@ -598,6 +581,32 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> { None => Some(self).map(Temporary::from_rooted), } } + + // https://dom.spec.whatwg.org/#locate-a-namespace-prefix + fn lookup_prefix(self, namespace: Option<DOMString>) -> Option<DOMString> { + for node in NodeCast::from_ref(self).inclusive_ancestors() { + match ElementCast::to_ref(node.root().r()) { + Some(element) => { + // Step 1. + if element.GetNamespaceURI() == namespace && element.GetPrefix().is_some() { + return element.GetPrefix(); + } + + // Step 2. + let attrs = element.Attributes().root(); + for i in 0..attrs.r().Length() { + let attr = attrs.r().Item(i).unwrap().root(); + if attr.r().GetPrefix() == Some("xmlns".to_owned()) && + Some(attr.r().Value()) == namespace { + return Some(attr.r().LocalName()); + } + } + }, + None => return None, + } + } + None + } } pub trait FocusElementHelpers { @@ -1264,6 +1273,16 @@ impl<'a> ElementMethods for JSRef<'a, Element> { NodeCast::from_ref(self).child_elements().count() as u32 } + // https://dom.spec.whatwg.org/#dom-parentnode-prepend + fn Prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).prepend(nodes) + } + + // https://dom.spec.whatwg.org/#dom-parentnode-append + fn Append(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).append(nodes) + } + // https://dom.spec.whatwg.org/#dom-parentnode-queryselector fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { let root: JSRef<Node> = NodeCast::from_ref(self); @@ -1276,6 +1295,21 @@ impl<'a> ElementMethods for JSRef<'a, Element> { root.query_selector_all(selectors) } + // https://dom.spec.whatwg.org/#dom-childnode-before + fn Before(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).before(nodes) + } + + // https://dom.spec.whatwg.org/#dom-childnode-after + fn After(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).after(nodes) + } + + // https://dom.spec.whatwg.org/#dom-childnode-replacewith + fn ReplaceWith(self, nodes: Vec<NodeOrString>) -> ErrorResult { + NodeCast::from_ref(self).replace_with(nodes) + } + // https://dom.spec.whatwg.org/#dom-childnode-remove fn Remove(self) { let node: JSRef<Node> = NodeCast::from_ref(self); diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index a4da4a148d6..80e5d476837 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -107,16 +107,16 @@ impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> { } - //TODO:https://html.spec.whatwg.org/multipage/semantics.html#the-a-element + //TODO:https://html.spec.whatwg.org/multipage/#the-a-element fn pre_click_activation(&self) { } - //TODO:https://html.spec.whatwg.org/multipage/semantics.html#the-a-element - // https://html.spec.whatwg.org/multipage/interaction.html#run-canceled-activation-steps + //TODO:https://html.spec.whatwg.org/multipage/#the-a-element + // https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps fn canceled_activation(&self) { } - //https://html.spec.whatwg.org/multipage/semantics.html#the-a-element:activation-behaviour + //https://html.spec.whatwg.org/multipage/#the-a-element:activation-behaviour fn activation_behavior(&self, event: JSRef<Event>, target: JSRef<EventTarget>) { //Step 1. If the node document is not fully active, abort. let doc = document_from_node(*self).root(); @@ -153,7 +153,7 @@ impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> { } } - //TODO:https://html.spec.whatwg.org/multipage/semantics.html#the-a-element + //TODO:https://html.spec.whatwg.org/multipage/#the-a-element fn implicit_submission(&self, _ctrlKey: bool, _shiftKey: bool, _altKey: bool, _metaKey: bool) { } } diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index 719a010cac9..7129681ea41 100644 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -187,16 +187,16 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> { !(node.get_disabled_state()) } - // https://html.spec.whatwg.org/multipage/interaction.html#run-pre-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps // https://html.spec.whatwg.org/multipage/#the-button-element:activation-behavior fn pre_click_activation(&self) { } - // https://html.spec.whatwg.org/multipage/interaction.html#run-canceled-activation-steps + // https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps fn canceled_activation(&self) { } - // https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) { let ty = self.button_type.get(); match ty { diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index e4fc68565a3..0a30989442b 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -2,15 +2,17 @@ * 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 canvas::canvas_paint_task::CanvasMsg; +use canvas::canvas_msg::CanvasMsg; use dom::attr::Attr; use dom::attr::AttrHelpers; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; use dom::bindings::global::GlobalRef; -use dom::bindings::js::{MutNullableJS, JSRef, LayoutJS, Temporary}; +use dom::bindings::js::{MutNullableJS, JSRef, LayoutJS, Temporary, Unrooted}; +use dom::bindings::utils::{Reflectable}; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; use dom::document::Document; use dom::element::{Element, AttributeHandlers}; @@ -19,6 +21,7 @@ use dom::element::ElementTypeId; use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::node::{Node, NodeTypeId, window_from_node}; use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{WebGLRenderingContext, LayoutCanvasWebGLRenderingContextHelpers}; use util::str::{DOMString, parse_unsigned_integer}; @@ -34,7 +37,8 @@ const DEFAULT_HEIGHT: u32 = 150; #[dom_struct] pub struct HTMLCanvasElement { htmlelement: HTMLElement, - context: MutNullableJS<CanvasRenderingContext2D>, + context_2d: MutNullableJS<CanvasRenderingContext2D>, + context_webgl: MutNullableJS<WebGLRenderingContext>, width: Cell<u32>, height: Cell<u32>, } @@ -49,7 +53,8 @@ impl HTMLCanvasElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLCanvasElement { HTMLCanvasElement { htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLCanvasElement, localName, prefix, document), - context: Default::default(), + context_2d: Default::default(), + context_webgl: Default::default(), width: Cell::new(DEFAULT_WIDTH), height: Cell::new(DEFAULT_HEIGHT), } @@ -60,6 +65,20 @@ impl HTMLCanvasElement { let element = HTMLCanvasElement::new_inherited(localName, prefix, document); Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(context) = self.context_2d.get() { + context.root().r().recreate(size) + } + if let Some(context) = self.context_webgl.get() { + context.root().r().recreate(size) + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D(self.width.get() as i32, self.height.get() as i32) + } } pub trait LayoutHTMLCanvasElementHelpers { @@ -74,8 +93,16 @@ pub trait LayoutHTMLCanvasElementHelpers { impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { #[allow(unsafe_code)] unsafe fn get_renderer(&self) -> Option<Sender<CanvasMsg>> { - let context = (*self.unsafe_get()).context.get_inner_as_layout(); - context.map(|cx| cx.get_renderer()) + let ref canvas = *self.unsafe_get(); + if canvas.context_2d.get().is_some() { + let context = canvas.context_2d.get_inner_as_layout(); + context.map(|cx| cx.get_renderer()) + } else if canvas.context_webgl.get().is_some() { + let context = canvas.context_webgl.get_inner_as_layout(); + context.map(|cx| cx.get_renderer()) + } else { + None + } } #[allow(unsafe_code)] @@ -90,18 +117,30 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { } pub trait HTMLCanvasElementHelpers { - fn get_size(&self) -> Size2D<i32>; fn get_2d_context(self) -> Temporary<CanvasRenderingContext2D>; + fn get_webgl_context(self) -> Temporary<WebGLRenderingContext>; fn is_valid(self) -> bool; } impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> { - fn get_size(&self) -> Size2D<i32> { - Size2D(self.Width() as i32, self.Height() as i32) + fn get_2d_context(self) -> Temporary<CanvasRenderingContext2D> { + let context = self.GetContext(String::from_str("2d")); + match context.unwrap() { + CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(context) => { + Temporary::new(context.root().r().unrooted()) + } + _ => panic!("Wrong Context Type: Expected 2d context"), + } } - fn get_2d_context(self) -> Temporary<CanvasRenderingContext2D> { - self.GetContext(String::from_str("2d")).unwrap() + fn get_webgl_context(self) -> Temporary<WebGLRenderingContext> { + let context = self.GetContext(String::from_str("webgl")); + match context.unwrap() { + CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(context) => { + return Temporary::new(context.root().r().unrooted()); + } + _ => panic!("Wrong Context Type: Expected webgl context"), + } } fn is_valid(self) -> bool { @@ -128,17 +167,27 @@ impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> { elem.set_uint_attribute(&atom!("height"), height) } - fn GetContext(self, id: DOMString) -> Option<Temporary<CanvasRenderingContext2D>> { - if id.as_slice() != "2d" { - return None; - } - - Some(self.context.or_init(|| { - let window = window_from_node(self).root(); - let (w, h) = (self.width.get() as i32, self.height.get() as i32); - CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, Size2D(w, h)) - })) - } + fn GetContext(self, id: DOMString) -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match id.as_slice() { + "2d" => { + let context_2d = self.context_2d.or_init(|| { + let window = window_from_node(self).root(); + let size = self.get_size(); + CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size) + }); + Some(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(Unrooted::from_temporary(context_2d))) + } + "webgl" | "experimental-webgl" => { + let context_webgl = self.context_webgl.or_init(|| { + let window = window_from_node(self).root(); + let size = self.get_size(); + WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size) + }); + Some(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(Unrooted::from_temporary(context_webgl))) + } + _ => return None + } + } } impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> { @@ -165,11 +214,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> { }; if recreate { - let (w, h) = (self.width.get() as i32, self.height.get() as i32); - match self.context.get() { - Some(context) => context.root().r().recreate(Size2D(w, h)), - None => () - } + self.recreate_contexts(); } } @@ -192,12 +237,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> { }; if recreate { - let (w, h) = (self.width.get() as i32, self.height.get() as i32); - match self.context.get() { - Some(context) => context.root().r().recreate(Size2D(w, h)), - None => () - } + self.recreate_contexts(); } } } - diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index a8043d27e18..68c097158dc 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -28,6 +28,7 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_n use dom::virtualmethods::VirtualMethods; use dom::window::WindowHelpers; +use msg::constellation_msg::FocusType; use util::str::DOMString; use string_cache::Atom; @@ -123,7 +124,7 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> { } } - // https://html.spec.whatwg.org/multipage/interaction.html#dom-click + // https://html.spec.whatwg.org/multipage/#dom-click fn Click(self) { let maybe_input: Option<JSRef<HTMLInputElement>> = HTMLInputElementCast::to_ref(self); if let Some(i) = maybe_input { @@ -136,30 +137,30 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> { element.as_maybe_activatable().map(|a| a.synthetic_click_activation(false, false, false, false)); } - // https://html.spec.whatwg.org/multipage/interaction.html#dom-focus + // https://html.spec.whatwg.org/multipage/#dom-focus fn Focus(self) { // TODO: Mark the element as locked for focus and run the focusing steps. - // https://html.spec.whatwg.org/multipage/interaction.html#focusing-steps + // https://html.spec.whatwg.org/multipage/#focusing-steps let element: JSRef<Element> = ElementCast::from_ref(self); let document = document_from_node(self).root(); let document = document.r(); document.begin_focus_transaction(); document.request_focus(element); - document.commit_focus_transaction(); + document.commit_focus_transaction(FocusType::Element); } - // https://html.spec.whatwg.org/multipage/interaction.html#dom-blur + // https://html.spec.whatwg.org/multipage/#dom-blur fn Blur(self) { // TODO: Run the unfocusing steps. let node: JSRef<Node> = NodeCast::from_ref(self); if !node.get_focus_state() { return; } - // https://html.spec.whatwg.org/multipage/interaction.html#unfocusing-steps + // https://html.spec.whatwg.org/multipage/#unfocusing-steps let document = document_from_node(self).root(); document.r().begin_focus_transaction(); // If `request_focus` is not called, focus will be set to None. - document.r().commit_focus_transaction(); + document.r().commit_focus_transaction(FocusType::Element); } } diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 613d22f36e8..8d492ab8c65 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -651,7 +651,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { } } - // https://html.spec.whatwg.org/multipage/interaction.html#run-pre-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps #[allow(unsafe_code)] fn pre_click_activation(&self) { let mut cache = self.activation_state.borrow_mut(); @@ -701,7 +701,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { } } - // https://html.spec.whatwg.org/multipage/interaction.html#run-canceled-activation-steps + // https://html.spec.whatwg.org/multipage/#run-canceled-activation-steps fn canceled_activation(&self) { let cache = self.activation_state.borrow(); let ty = self.input_type.get(); @@ -752,7 +752,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { } } - // https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps + // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) { let ty = self.input_type.get(); if self.activation_state.borrow().old_type != ty { diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs index ae730c102ac..6b82c63ea82 100644 --- a/components/script/dom/htmlobjectelement.rs +++ b/components/script/dom/htmlobjectelement.rs @@ -87,10 +87,10 @@ impl<'a> HTMLObjectElementMethods for JSRef<'a, HTMLObjectElement> { ValidityState::new(window.r()) } - // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-object-type + // https://html.spec.whatwg.org/multipage/#dom-object-type make_getter!(Type); - // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-object-type + // https://html.spec.whatwg.org/multipage/#dom-object-type make_setter!(SetType, "type"); } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 6bfdf6afd9b..b6066e7b746 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -44,18 +44,18 @@ use url::{Url, UrlParser}; pub struct HTMLScriptElement { htmlelement: HTMLElement, - /// https://html.spec.whatwg.org/multipage/scripting.html#already-started + /// https://html.spec.whatwg.org/multipage/#already-started already_started: Cell<bool>, - /// https://html.spec.whatwg.org/multipage/scripting.html#parser-inserted + /// https://html.spec.whatwg.org/multipage/#parser-inserted parser_inserted: Cell<bool>, - /// https://html.spec.whatwg.org/multipage/scripting.html#non-blocking + /// https://html.spec.whatwg.org/multipage/#non-blocking /// /// (currently unused) non_blocking: Cell<bool>, - /// https://html.spec.whatwg.org/multipage/scripting.html#ready-to-be-parser-executed + /// https://html.spec.whatwg.org/multipage/#ready-to-be-parser-executed /// /// (currently unused) ready_to_be_parser_executed: Cell<bool>, @@ -63,7 +63,7 @@ pub struct HTMLScriptElement { /// Document of the parser that created this element parser_document: JS<Document>, - /// https://html.spec.whatwg.org/multipage/scripting.html#concept-script-encoding + /// https://html.spec.whatwg.org/multipage/#concept-script-encoding block_character_encoding: DOMRefCell<EncodingRef>, } @@ -153,7 +153,7 @@ pub enum ScriptOrigin { impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> { fn prepare(self) { - // https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script + // https://html.spec.whatwg.org/multipage/#prepare-a-script // Step 1. if self.already_started.get() { return; diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 6c7204f7765..9f33d5ec195 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -324,6 +324,7 @@ pub mod urlsearchparams; pub mod userscripts; pub mod validitystate; pub mod virtualmethods; +pub mod webglrenderingcontext; pub mod websocket; pub mod window; pub mod worker; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index b3fed387468..ca7d7598480 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -6,6 +6,7 @@ use dom::attr::{Attr, AttrHelpers}; use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; @@ -18,8 +19,9 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast, ElementDerived use dom::bindings::codegen::InheritTypes::{HTMLLegendElementDerived, HTMLFieldSetElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, NodeBase, NodeDerived}; use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, TextCast}; +use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::conversions; -use dom::bindings::error::Fallible; +use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{NotFound, HierarchyRequest, Syntax}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, JSRef, LayoutJS, RootedReference, Temporary, Root, Unrooted}; @@ -499,6 +501,12 @@ pub trait NodeHelpers { fn get_bounding_content_box(self) -> Rect<Au>; fn get_content_boxes(self) -> Vec<Rect<Au>>; + fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult; + fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult; + fn replace_with(self, nodes: Vec<NodeOrString>) -> ErrorResult; + fn prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult; + fn append(self, nodes: Vec<NodeOrString>) -> ErrorResult; + fn query_selector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>; #[allow(unsafe_code)] unsafe fn query_selector_iter(self, selectors: DOMString) -> Fallible<QuerySelectorIterator>; @@ -512,6 +520,7 @@ pub trait NodeHelpers { fn teardown(self); fn parse_fragment(self, markup: DOMString) -> Fallible<Temporary<DocumentFragment>>; + } impl<'a> NodeHelpers for JSRef<'a, Node> { @@ -802,6 +811,80 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { window_from_node(self).root().r().content_boxes_query(self.to_trusted_node_address()) } + // https://dom.spec.whatwg.org/#dom-childnode-before + fn before(self, nodes: Vec<NodeOrString>) -> ErrorResult { + match self.parent_node().root() { + None => { + // Step 1. + Ok(()) + }, + Some(ref parent_node) => { + // Step 2. + let doc = self.owner_doc().root(); + let node = try!(doc.r().node_from_nodes_and_strings(nodes)).root(); + // Step 3. + Node::pre_insert(node.r(), parent_node.r(), + Some(self)).map(|_| ()) + }, + } + } + + // https://dom.spec.whatwg.org/#dom-childnode-after + fn after(self, nodes: Vec<NodeOrString>) -> ErrorResult { + match self.parent_node().root() { + None => { + // Step 1. + Ok(()) + }, + Some(ref parent_node) => { + // Step 2. + let doc = self.owner_doc().root(); + let node = try!(doc.r().node_from_nodes_and_strings(nodes)).root(); + // Step 3. + // FIXME(https://github.com/servo/servo/issues/5720) + let next_sibling = self.next_sibling().root(); + Node::pre_insert(node.r(), parent_node.r(), + next_sibling.r()).map(|_| ()) + }, + } + } + + // https://dom.spec.whatwg.org/#dom-childnode-replacewith + fn replace_with(self, nodes: Vec<NodeOrString>) -> ErrorResult { + match self.parent_node().root() { + None => { + // Step 1. + Ok(()) + }, + Some(ref parent_node) => { + // Step 2. + let doc = self.owner_doc().root(); + let node = try!(doc.r().node_from_nodes_and_strings(nodes)).root(); + // Step 3. + parent_node.r().ReplaceChild(node.r(), self).map(|_| ()) + }, + } + } + + // https://dom.spec.whatwg.org/#dom-parentnode-prepend + fn prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { + // Step 1. + let doc = self.owner_doc().root(); + let node = try!(doc.r().node_from_nodes_and_strings(nodes)).root(); + // Step 2. + let first_child = self.first_child().root(); + Node::pre_insert(node.r(), self, first_child.r()).map(|_| ()) + } + + // https://dom.spec.whatwg.org/#dom-parentnode-append + fn append(self, nodes: Vec<NodeOrString>) -> ErrorResult { + // Step 1. + let doc = self.owner_doc().root(); + let node = try!(doc.r().node_from_nodes_and_strings(nodes)).root(); + // Step 2. + self.AppendChild(node.r()).map(|_| ()) + } + // https://dom.spec.whatwg.org/#dom-parentnode-queryselector fn query_selector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { // Step 1. @@ -2278,9 +2361,27 @@ impl<'a> NodeMethods for JSRef<'a, Node> { } // https://dom.spec.whatwg.org/#dom-node-lookupprefix - fn LookupPrefix(self, _prefix: Option<DOMString>) -> Option<DOMString> { - // FIXME (#1826) implement. - None + fn LookupPrefix(self, namespace: Option<DOMString>) -> Option<DOMString> { + // Step 1. + if null_str_as_empty(&namespace).is_empty() { + return None; + } + + // Step 2. + match self.type_id() { + NodeTypeId::Element(..) => ElementCast::to_ref(self).unwrap().lookup_prefix(namespace), + NodeTypeId::Document => { + DocumentCast::to_ref(self).unwrap().GetDocumentElement().and_then(|element| { + element.root().r().lookup_prefix(namespace) + }) + }, + NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => None, + _ => { + self.GetParentElement().and_then(|element| { + element.root().r().lookup_prefix(namespace) + }) + } + } } // https://dom.spec.whatwg.org/#dom-node-lookupnamespaceuri @@ -2517,4 +2618,3 @@ pub enum NodeDamage { /// Other parts of a node changed; attributes, text content, etc. OtherNodeDamage, } - diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index 9ec49555c9c..13871b43c29 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -133,7 +133,7 @@ trait PrivateStorageHelpers { } impl<'a> PrivateStorageHelpers for JSRef<'a, Storage> { - /// https://html.spec.whatwg.org/multipage/webstorage.html#send-a-storage-notification + /// https://html.spec.whatwg.org/multipage/#send-a-storage-notification fn broadcast_change_notification(self, key: Option<DOMString>, old_value: Option<DOMString>, new_value: Option<DOMString>){ let global_root = self.global.root(); diff --git a/components/script/dom/urlsearchparams.rs b/components/script/dom/urlsearchparams.rs index 0c234cb2664..1e418c4b6f8 100644 --- a/components/script/dom/urlsearchparams.rs +++ b/components/script/dom/urlsearchparams.rs @@ -140,7 +140,7 @@ impl URLSearchParamsHelpers for URLSearchParams { // Encode everything else using 'percented-encoded bytes' // https://url.spec.whatwg.org/#percent-encode - a => format!("%{:X}", a).into_bytes(), + a => format!("%{:02X}", a).into_bytes(), }; buf.push_all(&append); } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs new file mode 100644 index 00000000000..07c47970476 --- /dev/null +++ b/components/script/dom/webglrenderingcontext.rs @@ -0,0 +1,75 @@ +/* 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 canvas::webgl_paint_task::WebGLPaintTask; +use canvas::canvas_msg::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg}; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; +use dom::bindings::global::{GlobalRef, GlobalField}; +use dom::bindings::js::{JS, JSRef, LayoutJS, Temporary}; +use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::htmlcanvaselement::{HTMLCanvasElement}; +use geom::size::Size2D; +use std::sync::mpsc::{Sender}; + +#[dom_struct] +pub struct WebGLRenderingContext { + reflector_: Reflector, + global: GlobalField, + renderer: Sender<CanvasMsg>, + canvas: JS<HTMLCanvasElement>, +} + +impl WebGLRenderingContext { + fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) + -> WebGLRenderingContext { + WebGLRenderingContext { + reflector_: Reflector::new(), + global: GlobalField::from_rooted(&global), + renderer: WebGLPaintTask::start(size), + canvas: JS::from_rooted(canvas), + } + } + + pub fn new(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) + -> Temporary<WebGLRenderingContext> { + reflect_dom_object(box WebGLRenderingContext::new_inherited(global, canvas, size), + global, WebGLRenderingContextBinding::Wrap) + } + + pub fn recreate(&self, size: Size2D<i32>) { + self.renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap(); + } + +} + +#[unsafe_destructor] +impl Drop for WebGLRenderingContext { + fn drop(&mut self) { + self.renderer.send(CanvasMsg::Common(CanvasCommonMsg::Close)).unwrap(); + } +} + +impl<'a> WebGLRenderingContextMethods for JSRef<'a, WebGLRenderingContext> { + fn Clear(self, mask: u32) -> () { + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::Clear(mask))).unwrap() + } + + fn ClearColor(self, red: f32, green: f32, blue: f32, alpha: f32) -> (){ + self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::ClearColor(red, green, blue, alpha))).unwrap() + } +} + +pub trait LayoutCanvasWebGLRenderingContextHelpers { + #[allow(unsafe_code)] + unsafe fn get_renderer(&self) -> Sender<CanvasMsg>; +} + +impl LayoutCanvasWebGLRenderingContextHelpers for LayoutJS<WebGLRenderingContext> { + #[allow(unsafe_code)] + unsafe fn get_renderer(&self) -> Sender<CanvasMsg> { + (*self.unsafe_get()).renderer.clone() + } +} + diff --git a/components/script/dom/webidls/CanvasRenderingContext2D.webidl b/components/script/dom/webidls/CanvasRenderingContext2D.webidl index 2805a273550..44f9c707600 100644 --- a/components/script/dom/webidls/CanvasRenderingContext2D.webidl +++ b/components/script/dom/webidls/CanvasRenderingContext2D.webidl @@ -26,8 +26,8 @@ interface CanvasRenderingContext2D { //void commit(); // push the image to the output bitmap // state - //void save(); // push state on state stack - //void restore(); // pop state stack and restore state + void save(); // push state on state stack + void restore(); // pop state stack and restore state // transformations (default transform is the identity matrix) // attribute SVGMatrix currentTransform; @@ -171,7 +171,7 @@ interface CanvasPathMethods { unrestricted double radius); // NOT IMPLEMENTED [LenientFloat] void arcTo(double x1, double y1, double x2, double y2, double radiusX, double radiusY, double rotation); - //void rect(double x, double y, double w, double h); + void rect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); [Throws] void arc(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise = false); diff --git a/components/script/dom/webidls/ChildNode.webidl b/components/script/dom/webidls/ChildNode.webidl index de8d8271537..7205d08b05e 100644 --- a/components/script/dom/webidls/ChildNode.webidl +++ b/components/script/dom/webidls/ChildNode.webidl @@ -9,10 +9,12 @@ [NoInterfaceObject] interface ChildNode { -// Not implemented yet: -// void before((Node or DOMString)... nodes); -// void after((Node or DOMString)... nodes); -// void replace((Node or DOMString)... nodes); + [Throws] + void before((Node or DOMString)... nodes); + [Throws] + void after((Node or DOMString)... nodes); + [Throws] + void replaceWith((Node or DOMString)... nodes); void remove(); }; diff --git a/components/script/dom/webidls/HTMLCanvasElement.webidl b/components/script/dom/webidls/HTMLCanvasElement.webidl index e1192d215f8..2458ce41a1f 100644 --- a/components/script/dom/webidls/HTMLCanvasElement.webidl +++ b/components/script/dom/webidls/HTMLCanvasElement.webidl @@ -3,8 +3,8 @@ * 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/. */ -// https://www.whatwg.org/html/#htmlcanvaselement -//typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext; +// https://www.whatwg.org/html/#htmlcanvaselement +typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext; interface HTMLCanvasElement : HTMLElement { [Pure] @@ -12,8 +12,7 @@ interface HTMLCanvasElement : HTMLElement { [Pure] attribute unsigned long height; - //RenderingContext? getContext(DOMString contextId, any... arguments); - CanvasRenderingContext2D? getContext(DOMString contextId); + RenderingContext? getContext(DOMString contextId); //boolean probablySupportsContext(DOMString contextId, any... arguments); //void setContext(RenderingContext context); diff --git a/components/script/dom/webidls/ParentNode.webidl b/components/script/dom/webidls/ParentNode.webidl index 6d1d3037265..c7dc425a1fd 100644 --- a/components/script/dom/webidls/ParentNode.webidl +++ b/components/script/dom/webidls/ParentNode.webidl @@ -18,9 +18,10 @@ interface ParentNode { [Pure] readonly attribute unsigned long childElementCount; - // Not implemented yet - // void prepend((Node or DOMString)... nodes); - // void append((Node or DOMString)... nodes); + [Throws] + void prepend((Node or DOMString)... nodes); + [Throws] + void append((Node or DOMString)... nodes); //Element? query(DOMString relativeSelectors); //[NewObject] diff --git a/components/script/dom/webidls/Storage.webidl b/components/script/dom/webidls/Storage.webidl index 4a469c4da0e..eb3007c2815 100644 --- a/components/script/dom/webidls/Storage.webidl +++ b/components/script/dom/webidls/Storage.webidl @@ -4,7 +4,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * The origin of this IDL file is - * https://html.spec.whatwg.org/multipage/webstorage.html#webstorage + * https://html.spec.whatwg.org/multipage/#webstorage * */ diff --git a/components/script/dom/webidls/StorageEvent.webidl b/components/script/dom/webidls/StorageEvent.webidl index 18386d09492..55087a4b731 100644 --- a/components/script/dom/webidls/StorageEvent.webidl +++ b/components/script/dom/webidls/StorageEvent.webidl @@ -4,7 +4,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. * * Interface for a client side storage. See - * https://html.spec.whatwg.org/multipage/webstorage.html#the-storageevent-interface + * https://html.spec.whatwg.org/multipage/#the-storageevent-interface * for more information. * * Event sent to a window when a storage area changes. diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl new file mode 100644 index 00000000000..aa1d3535635 --- /dev/null +++ b/components/script/dom/webidls/WebGLRenderingContext.webidl @@ -0,0 +1,739 @@ +// AUTOGENERATED FILE -- DO NOT EDIT -- SEE Makefile +// +// WebGL IDL definitions scraped from the Khronos specification: +// https://www.khronos.org/registry/webgl/specs/latest/ +// +// This IDL depends on the typed array specification defined at: +// https://www.khronos.org/registry/typedarray/specs/latest/typedarrays.idl + +typedef unsigned long GLenum; +typedef boolean GLboolean; +typedef unsigned long GLbitfield; +typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */ +typedef short GLshort; +typedef long GLint; +typedef long GLsizei; +typedef long long GLintptr; +typedef long long GLsizeiptr; +// Ideally the typedef below would use 'unsigned byte', but that doesn't currently exist in Web IDL. +typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */ +typedef unsigned short GLushort; +typedef unsigned long GLuint; +typedef unrestricted float GLfloat; +typedef unrestricted float GLclampf; + + +dictionary WebGLContextAttributes { + GLboolean alpha = true; + GLboolean depth = true; + GLboolean stencil = false; + GLboolean antialias = true; + GLboolean premultipliedAlpha = true; + GLboolean preserveDrawingBuffer = false; + GLboolean preferLowPowerToHighPerformance = false; + GLboolean failIfMajorPerformanceCaveat = false; +}; + +//interface WebGLObject { +//}; + +//interface WebGLBuffer : WebGLObject { +//}; + +//interface WebGLFramebuffer : WebGLObject { +//}; + +//interface WebGLProgram : WebGLObject { +//}; + +//interface WebGLRenderbuffer : WebGLObject { +//}; + +//interface WebGLShader : WebGLObject { +//}; + +//interface WebGLTexture : WebGLObject { +//}; + +//interface WebGLUniformLocation { +//}; + +//interface WebGLActiveInfo { +// readonly attribute GLint size; +// readonly attribute GLenum type; +// readonly attribute DOMString name; +//}; + +//interface WebGLShaderPrecisionFormat { +// readonly attribute GLint rangeMin; +// readonly attribute GLint rangeMax; +// readonly attribute GLint precision; +//}; + +[NoInterfaceObject] +interface WebGLRenderingContextBase +{ + + /* ClearBufferMask */ + //const GLenum DEPTH_BUFFER_BIT = 0x00000100; + //const GLenum STENCIL_BUFFER_BIT = 0x00000400; + const GLenum COLOR_BUFFER_BIT = 0x00004000; + + /* BeginMode */ + //const GLenum POINTS = 0x0000; + //const GLenum LINES = 0x0001; + //const GLenum LINE_LOOP = 0x0002; + //const GLenum LINE_STRIP = 0x0003; + //const GLenum TRIANGLES = 0x0004; + //const GLenum TRIANGLE_STRIP = 0x0005; + //const GLenum TRIANGLE_FAN = 0x0006; + + /* AlphaFunction (not supported in ES20) */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* BlendingFactorDest */ + //const GLenum ZERO = 0; + //const GLenum ONE = 1; + //const GLenum SRC_COLOR = 0x0300; + //const GLenum ONE_MINUS_SRC_COLOR = 0x0301; + //const GLenum SRC_ALPHA = 0x0302; + //const GLenum ONE_MINUS_SRC_ALPHA = 0x0303; + //const GLenum DST_ALPHA = 0x0304; + //const GLenum ONE_MINUS_DST_ALPHA = 0x0305; + + /* BlendingFactorSrc */ + /* ZERO */ + /* ONE */ + //const GLenum DST_COLOR = 0x0306; + //const GLenum ONE_MINUS_DST_COLOR = 0x0307; + //const GLenum SRC_ALPHA_SATURATE = 0x0308; + /* SRC_ALPHA */ + /* ONE_MINUS_SRC_ALPHA */ + /* DST_ALPHA */ + /* ONE_MINUS_DST_ALPHA */ + + /* BlendEquationSeparate */ + //const GLenum FUNC_ADD = 0x8006; + //const GLenum BLEND_EQUATION = 0x8009; + //const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */ + //const GLenum BLEND_EQUATION_ALPHA = 0x883D; + + /* BlendSubtract */ + //const GLenum FUNC_SUBTRACT = 0x800A; + //const GLenum FUNC_REVERSE_SUBTRACT = 0x800B; + + /* Separate Blend Functions */ + //const GLenum BLEND_DST_RGB = 0x80C8; + //const GLenum BLEND_SRC_RGB = 0x80C9; + //const GLenum BLEND_DST_ALPHA = 0x80CA; + //const GLenum BLEND_SRC_ALPHA = 0x80CB; + //const GLenum CONSTANT_COLOR = 0x8001; + //const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002; + //const GLenum CONSTANT_ALPHA = 0x8003; + //const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004; + //const GLenum BLEND_COLOR = 0x8005; + + /* Buffer Objects */ + //const GLenum ARRAY_BUFFER = 0x8892; + //const GLenum ELEMENT_ARRAY_BUFFER = 0x8893; + //const GLenum ARRAY_BUFFER_BINDING = 0x8894; + //const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895; + + //const GLenum STREAM_DRAW = 0x88E0; + //const GLenum STATIC_DRAW = 0x88E4; + //const GLenum DYNAMIC_DRAW = 0x88E8; + + //const GLenum BUFFER_SIZE = 0x8764; + //const GLenum BUFFER_USAGE = 0x8765; + + //const GLenum CURRENT_VERTEX_ATTRIB = 0x8626; + + /* CullFaceMode */ + //const GLenum FRONT = 0x0404; + //const GLenum BACK = 0x0405; + //const GLenum FRONT_AND_BACK = 0x0408; + + /* DepthFunction */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* EnableCap */ + /* TEXTURE_2D */ + //const GLenum CULL_FACE = 0x0B44; + //const GLenum BLEND = 0x0BE2; + //const GLenum DITHER = 0x0BD0; + //const GLenum STENCIL_TEST = 0x0B90; + //const GLenum DEPTH_TEST = 0x0B71; + //const GLenum SCISSOR_TEST = 0x0C11; + //const GLenum POLYGON_OFFSET_FILL = 0x8037; + //const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E; + //const GLenum SAMPLE_COVERAGE = 0x80A0; + + /* ErrorCode */ + //const GLenum NO_ERROR = 0; + //const GLenum INVALID_ENUM = 0x0500; + //const GLenum INVALID_VALUE = 0x0501; + //const GLenum INVALID_OPERATION = 0x0502; + //const GLenum OUT_OF_MEMORY = 0x0505; + + /* FrontFaceDirection */ + //const GLenum CW = 0x0900; + //const GLenum CCW = 0x0901; + + /* GetPName */ + //const GLenum LINE_WIDTH = 0x0B21; + //const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D; + //const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E; + //const GLenum CULL_FACE_MODE = 0x0B45; + //const GLenum FRONT_FACE = 0x0B46; + //const GLenum DEPTH_RANGE = 0x0B70; + //const GLenum DEPTH_WRITEMASK = 0x0B72; + //const GLenum DEPTH_CLEAR_VALUE = 0x0B73; + //const GLenum DEPTH_FUNC = 0x0B74; + //const GLenum STENCIL_CLEAR_VALUE = 0x0B91; + //const GLenum STENCIL_FUNC = 0x0B92; + //const GLenum STENCIL_FAIL = 0x0B94; + //const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95; + //const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96; + //const GLenum STENCIL_REF = 0x0B97; + //const GLenum STENCIL_VALUE_MASK = 0x0B93; + //const GLenum STENCIL_WRITEMASK = 0x0B98; + //const GLenum STENCIL_BACK_FUNC = 0x8800; + //const GLenum STENCIL_BACK_FAIL = 0x8801; + //const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802; + //const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803; + //const GLenum STENCIL_BACK_REF = 0x8CA3; + //const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4; + //const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5; + //const GLenum VIEWPORT = 0x0BA2; + //const GLenum SCISSOR_BOX = 0x0C10; + /* SCISSOR_TEST */ + //const GLenum COLOR_CLEAR_VALUE = 0x0C22; + //const GLenum COLOR_WRITEMASK = 0x0C23; + //const GLenum UNPACK_ALIGNMENT = 0x0CF5; + //const GLenum PACK_ALIGNMENT = 0x0D05; + //const GLenum MAX_TEXTURE_SIZE = 0x0D33; + //const GLenum MAX_VIEWPORT_DIMS = 0x0D3A; + //const GLenum SUBPIXEL_BITS = 0x0D50; + //const GLenum RED_BITS = 0x0D52; + //const GLenum GREEN_BITS = 0x0D53; + //const GLenum BLUE_BITS = 0x0D54; + //const GLenum ALPHA_BITS = 0x0D55; + //const GLenum DEPTH_BITS = 0x0D56; + //const GLenum STENCIL_BITS = 0x0D57; + //const GLenum POLYGON_OFFSET_UNITS = 0x2A00; + /* POLYGON_OFFSET_FILL */ + //const GLenum POLYGON_OFFSET_FACTOR = 0x8038; + //const GLenum TEXTURE_BINDING_2D = 0x8069; + //const GLenum SAMPLE_BUFFERS = 0x80A8; + //const GLenum SAMPLES = 0x80A9; + //const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA; + //const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB; + + /* GetTextureParameter */ + /* TEXTURE_MAG_FILTER */ + /* TEXTURE_MIN_FILTER */ + /* TEXTURE_WRAP_S */ + /* TEXTURE_WRAP_T */ + + //const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3; + + /* HintMode */ + //const GLenum DONT_CARE = 0x1100; + //const GLenum FASTEST = 0x1101; + //const GLenum NICEST = 0x1102; + + /* HintTarget */ + //const GLenum GENERATE_MIPMAP_HINT = 0x8192; + + /* DataType */ + //const GLenum BYTE = 0x1400; + //const GLenum UNSIGNED_BYTE = 0x1401; + //const GLenum SHORT = 0x1402; + //const GLenum UNSIGNED_SHORT = 0x1403; + //const GLenum INT = 0x1404; + //const GLenum UNSIGNED_INT = 0x1405; + //const GLenum FLOAT = 0x1406; + + /* PixelFormat */ + //const GLenum DEPTH_COMPONENT = 0x1902; + //const GLenum ALPHA = 0x1906; + //const GLenum RGB = 0x1907; + //const GLenum RGBA = 0x1908; + //const GLenum LUMINANCE = 0x1909; + //const GLenum LUMINANCE_ALPHA = 0x190A; + + /* PixelType */ + /* UNSIGNED_BYTE */ + //const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033; + //const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034; + //const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363; + + /* Shaders */ + //const GLenum FRAGMENT_SHADER = 0x8B30; + //const GLenum VERTEX_SHADER = 0x8B31; + //const GLenum MAX_VERTEX_ATTRIBS = 0x8869; + //const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; + //const GLenum MAX_VARYING_VECTORS = 0x8DFC; + //const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D; + //const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; + //const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872; + //const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD; + //const GLenum SHADER_TYPE = 0x8B4F; + //const GLenum DELETE_STATUS = 0x8B80; + //const GLenum LINK_STATUS = 0x8B82; + //const GLenum VALIDATE_STATUS = 0x8B83; + //const GLenum ATTACHED_SHADERS = 0x8B85; + //const GLenum ACTIVE_UNIFORMS = 0x8B86; + //const GLenum ACTIVE_ATTRIBUTES = 0x8B89; + //const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C; + //const GLenum CURRENT_PROGRAM = 0x8B8D; + + /* StencilFunction */ + //const GLenum NEVER = 0x0200; + //const GLenum LESS = 0x0201; + //const GLenum EQUAL = 0x0202; + //const GLenum LEQUAL = 0x0203; + //const GLenum GREATER = 0x0204; + //const GLenum NOTEQUAL = 0x0205; + //const GLenum GEQUAL = 0x0206; + //const GLenum ALWAYS = 0x0207; + + /* StencilOp */ + /* ZERO */ + //const GLenum KEEP = 0x1E00; + //const GLenum REPLACE = 0x1E01; + //const GLenum INCR = 0x1E02; + //const GLenum DECR = 0x1E03; + //const GLenum INVERT = 0x150A; + //const GLenum INCR_WRAP = 0x8507; + //const GLenum DECR_WRAP = 0x8508; + + /* StringName */ + //const GLenum VENDOR = 0x1F00; + //const GLenum RENDERER = 0x1F01; + //const GLenum VERSION = 0x1F02; + + /* TextureMagFilter */ + //const GLenum NEAREST = 0x2600; + //const GLenum LINEAR = 0x2601; + + /* TextureMinFilter */ + /* NEAREST */ + /* LINEAR */ + //const GLenum NEAREST_MIPMAP_NEAREST = 0x2700; + //const GLenum LINEAR_MIPMAP_NEAREST = 0x2701; + //const GLenum NEAREST_MIPMAP_LINEAR = 0x2702; + //const GLenum LINEAR_MIPMAP_LINEAR = 0x2703; + + /* TextureParameterName */ + //const GLenum TEXTURE_MAG_FILTER = 0x2800; + //const GLenum TEXTURE_MIN_FILTER = 0x2801; + //const GLenum TEXTURE_WRAP_S = 0x2802; + //const GLenum TEXTURE_WRAP_T = 0x2803; + + /* TextureTarget */ + //const GLenum TEXTURE_2D = 0x0DE1; + //const GLenum TEXTURE = 0x1702; + + //const GLenum TEXTURE_CUBE_MAP = 0x8513; + //const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514; + //const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + //const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + //const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + //const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + //const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + //const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + //const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; + + /* TextureUnit */ + //const GLenum TEXTURE0 = 0x84C0; + //const GLenum TEXTURE1 = 0x84C1; + //const GLenum TEXTURE2 = 0x84C2; + //const GLenum TEXTURE3 = 0x84C3; + //const GLenum TEXTURE4 = 0x84C4; + //const GLenum TEXTURE5 = 0x84C5; + //const GLenum TEXTURE6 = 0x84C6; + //const GLenum TEXTURE7 = 0x84C7; + //const GLenum TEXTURE8 = 0x84C8; + //const GLenum TEXTURE9 = 0x84C9; + //const GLenum TEXTURE10 = 0x84CA; + //const GLenum TEXTURE11 = 0x84CB; + //const GLenum TEXTURE12 = 0x84CC; + //const GLenum TEXTURE13 = 0x84CD; + //const GLenum TEXTURE14 = 0x84CE; + //const GLenum TEXTURE15 = 0x84CF; + //const GLenum TEXTURE16 = 0x84D0; + //const GLenum TEXTURE17 = 0x84D1; + //const GLenum TEXTURE18 = 0x84D2; + //const GLenum TEXTURE19 = 0x84D3; + //const GLenum TEXTURE20 = 0x84D4; + //const GLenum TEXTURE21 = 0x84D5; + //const GLenum TEXTURE22 = 0x84D6; + //const GLenum TEXTURE23 = 0x84D7; + //const GLenum TEXTURE24 = 0x84D8; + //const GLenum TEXTURE25 = 0x84D9; + //const GLenum TEXTURE26 = 0x84DA; + //const GLenum TEXTURE27 = 0x84DB; + //const GLenum TEXTURE28 = 0x84DC; + //const GLenum TEXTURE29 = 0x84DD; + //const GLenum TEXTURE30 = 0x84DE; + //const GLenum TEXTURE31 = 0x84DF; + //const GLenum ACTIVE_TEXTURE = 0x84E0; + + /* TextureWrapMode */ + //const GLenum REPEAT = 0x2901; + //const GLenum CLAMP_TO_EDGE = 0x812F; + //const GLenum MIRRORED_REPEAT = 0x8370; + + /* Uniform Types */ + //const GLenum FLOAT_VEC2 = 0x8B50; + //const GLenum FLOAT_VEC3 = 0x8B51; + //const GLenum FLOAT_VEC4 = 0x8B52; + //const GLenum INT_VEC2 = 0x8B53; + //const GLenum INT_VEC3 = 0x8B54; + //const GLenum INT_VEC4 = 0x8B55; + //const GLenum BOOL = 0x8B56; + //const GLenum BOOL_VEC2 = 0x8B57; + //const GLenum BOOL_VEC3 = 0x8B58; + //const GLenum BOOL_VEC4 = 0x8B59; + //const GLenum FLOAT_MAT2 = 0x8B5A; + //const GLenum FLOAT_MAT3 = 0x8B5B; + //const GLenum FLOAT_MAT4 = 0x8B5C; + //const GLenum SAMPLER_2D = 0x8B5E; + //const GLenum SAMPLER_CUBE = 0x8B60; + + /* Vertex Arrays */ + //const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622; + //const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623; + //const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624; + //const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625; + //const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A; + //const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645; + //const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F; + + /* Read Format */ + //const GLenum IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A; + //const GLenum IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B; + + /* Shader Source */ + //const GLenum COMPILE_STATUS = 0x8B81; + + /* Shader Precision-Specified Types */ + //const GLenum LOW_FLOAT = 0x8DF0; + //const GLenum MEDIUM_FLOAT = 0x8DF1; + //const GLenum HIGH_FLOAT = 0x8DF2; + //const GLenum LOW_INT = 0x8DF3; + //const GLenum MEDIUM_INT = 0x8DF4; + //const GLenum HIGH_INT = 0x8DF5; + + /* Framebuffer Object. */ + //const GLenum FRAMEBUFFER = 0x8D40; + //const GLenum RENDERBUFFER = 0x8D41; + + //const GLenum RGBA4 = 0x8056; + //const GLenum RGB5_A1 = 0x8057; + //const GLenum RGB565 = 0x8D62; + //const GLenum DEPTH_COMPONENT16 = 0x81A5; + //const GLenum STENCIL_INDEX = 0x1901; + //const GLenum STENCIL_INDEX8 = 0x8D48; + //const GLenum DEPTH_STENCIL = 0x84F9; + + //const GLenum RENDERBUFFER_WIDTH = 0x8D42; + //const GLenum RENDERBUFFER_HEIGHT = 0x8D43; + //const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44; + //const GLenum RENDERBUFFER_RED_SIZE = 0x8D50; + //const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51; + //const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52; + //const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53; + //const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54; + //const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55; + + //const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0; + //const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1; + //const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2; + //const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3; + + //const GLenum COLOR_ATTACHMENT0 = 0x8CE0; + //const GLenum DEPTH_ATTACHMENT = 0x8D00; + //const GLenum STENCIL_ATTACHMENT = 0x8D20; + //const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; + + //const GLenum NONE = 0; + + //const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5; + //const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6; + //const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7; + //const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9; + //const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD; + + //const GLenum FRAMEBUFFER_BINDING = 0x8CA6; + //const GLenum RENDERBUFFER_BINDING = 0x8CA7; + //const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8; + + //const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506; + + /* WebGL-specific enums */ + //const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240; + //const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; + //const GLenum CONTEXT_LOST_WEBGL = 0x9242; + //const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; + //const GLenum BROWSER_DEFAULT_WEBGL = 0x9244; + + //readonly attribute HTMLCanvasElement canvas; + //readonly attribute GLsizei drawingBufferWidth; + //readonly attribute GLsizei drawingBufferHeight; + + //[WebGLHandlesContextLoss] WebGLContextAttributes? getContextAttributes(); + //[WebGLHandlesContextLoss] boolean isContextLost(); + + //sequence<DOMString>? getSupportedExtensions(); + //object? getExtension(DOMString name); + + //void activeTexture(GLenum texture); + //void attachShader(WebGLProgram? program, WebGLShader? shader); + //void bindAttribLocation(WebGLProgram? program, GLuint index, DOMString name); + //void bindBuffer(GLenum target, WebGLBuffer? buffer); + //void bindFramebuffer(GLenum target, WebGLFramebuffer? framebuffer); + //void bindRenderbuffer(GLenum target, WebGLRenderbuffer? renderbuffer); + //void bindTexture(GLenum target, WebGLTexture? texture); + //void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + //void blendEquation(GLenum mode); + //void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + //void blendFunc(GLenum sfactor, GLenum dfactor); + //void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, + // GLenum srcAlpha, GLenum dstAlpha); + + //typedef (ArrayBuffer or ArrayBufferView) BufferDataSource; + //void bufferData(GLenum target, GLsizeiptr size, GLenum usage); + //void bufferData(GLenum target, BufferDataSource? data, GLenum usage); + //void bufferSubData(GLenum target, GLintptr offset, BufferDataSource? data); + + //[WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target); + void clear(GLbitfield mask); + void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + //void clearDepth(GLclampf depth); + //void clearStencil(GLint s); + //void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + //void compileShader(WebGLShader? shader); + + //void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, + // GLsizei width, GLsizei height, GLint border, + // ArrayBufferView data); + //void compressedTexSubImage2D(GLenum target, GLint level, + // GLint xoffset, GLint yoffset, + // GLsizei width, GLsizei height, GLenum format, + // ArrayBufferView data); + + //void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, + // GLint x, GLint y, GLsizei width, GLsizei height, + // GLint border); + //void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + // GLint x, GLint y, GLsizei width, GLsizei height); + + //WebGLBuffer? createBuffer(); + //WebGLFramebuffer? createFramebuffer(); + //WebGLProgram? createProgram(); + //WebGLRenderbuffer? createRenderbuffer(); + //WebGLShader? createShader(GLenum type); + //WebGLTexture? createTexture(); + + //void cullFace(GLenum mode); + + //void deleteBuffer(WebGLBuffer? buffer); + //void deleteFramebuffer(WebGLFramebuffer? framebuffer); + //void deleteProgram(WebGLProgram? program); + //void deleteRenderbuffer(WebGLRenderbuffer? renderbuffer); + //void deleteShader(WebGLShader? shader); + //void deleteTexture(WebGLTexture? texture); + + //void depthFunc(GLenum func); + //void depthMask(GLboolean flag); + //void depthRange(GLclampf zNear, GLclampf zFar); + //void detachShader(WebGLProgram? program, WebGLShader? shader); + //void disable(GLenum cap); + //void disableVertexAttribArray(GLuint index); + //void drawArrays(GLenum mode, GLint first, GLsizei count); + //void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset); + + //void enable(GLenum cap); + //void enableVertexAttribArray(GLuint index); + //void finish(); + //void flush(); + //void framebufferRenderbuffer(GLenum target, GLenum attachment, + // GLenum renderbuffertarget, + // WebGLRenderbuffer? renderbuffer); + //void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, + // WebGLTexture? texture, GLint level); + //void frontFace(GLenum mode); + + //void generateMipmap(GLenum target); + + //WebGLActiveInfo? getActiveAttrib(WebGLProgram? program, GLuint index); + //WebGLActiveInfo? getActiveUniform(WebGLProgram? program, GLuint index); + //sequence<WebGLShader>? getAttachedShaders(WebGLProgram? program); + + //[WebGLHandlesContextLoss] GLint getAttribLocation(WebGLProgram? program, DOMString name); + + //any getBufferParameter(GLenum target, GLenum pname); + //any getParameter(GLenum pname); + + //[WebGLHandlesContextLoss] GLenum getError(); + + //any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, + // GLenum pname); + //any getProgramParameter(WebGLProgram? program, GLenum pname); + //DOMString? getProgramInfoLog(WebGLProgram? program); + //any getRenderbufferParameter(GLenum target, GLenum pname); + //any getShaderParameter(WebGLShader? shader, GLenum pname); + //WebGLShaderPrecisionFormat? getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); + //DOMString? getShaderInfoLog(WebGLShader? shader); + + //DOMString? getShaderSource(WebGLShader? shader); + + //any getTexParameter(GLenum target, GLenum pname); + + //any getUniform(WebGLProgram? program, WebGLUniformLocation? location); + + //WebGLUniformLocation? getUniformLocation(WebGLProgram? program, DOMString name); + + //any getVertexAttrib(GLuint index, GLenum pname); + + //[WebGLHandlesContextLoss] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); + + //void hint(GLenum target, GLenum mode); + //[WebGLHandlesContextLoss] GLboolean isBuffer(WebGLBuffer? buffer); + //[WebGLHandlesContextLoss] GLboolean isEnabled(GLenum cap); + //[WebGLHandlesContextLoss] GLboolean isFramebuffer(WebGLFramebuffer? framebuffer); + //[WebGLHandlesContextLoss] GLboolean isProgram(WebGLProgram? program); + //[WebGLHandlesContextLoss] GLboolean isRenderbuffer(WebGLRenderbuffer? renderbuffer); + //[WebGLHandlesContextLoss] GLboolean isShader(WebGLShader? shader); + //[WebGLHandlesContextLoss] GLboolean isTexture(WebGLTexture? texture); + //void lineWidth(GLfloat width); + //void linkProgram(WebGLProgram? program); + //void pixelStorei(GLenum pname, GLint param); + //void polygonOffset(GLfloat factor, GLfloat units); + + //void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, + // GLenum format, GLenum type, ArrayBufferView? pixels); + + //void renderbufferStorage(GLenum target, GLenum internalformat, + // GLsizei width, GLsizei height); + //void sampleCoverage(GLclampf value, GLboolean invert); + //void scissor(GLint x, GLint y, GLsizei width, GLsizei height); + + //void shaderSource(WebGLShader? shader, DOMString source); + + //void stencilFunc(GLenum func, GLint ref, GLuint mask); + //void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + //void stencilMask(GLuint mask); + //void stencilMaskSeparate(GLenum face, GLuint mask); + //void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); + //void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + //typedef (ImageData or + // HTMLImageElement or + // HTMLCanvasElement or + // HTMLVideoElement) TexImageSource; + //void texImage2D(GLenum target, GLint level, GLenum internalformat, + // GLsizei width, GLsizei height, GLint border, GLenum format, + // GLenum type, ArrayBufferView? pixels); + //void texImage2D(GLenum target, GLint level, GLenum internalformat, + // GLenum format, GLenum type, TexImageSource? source); // May throw DOMException + + //void texParameterf(GLenum target, GLenum pname, GLfloat param); + //void texParameteri(GLenum target, GLenum pname, GLint param); + + //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + // GLsizei width, GLsizei height, + // GLenum format, GLenum type, ArrayBufferView? pixels); + //void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + // GLenum format, GLenum type, TexImageSource? source); // May throw DOMException + + //void uniform1f(WebGLUniformLocation? location, GLfloat x); + //void uniform1fv(WebGLUniformLocation? location, Float32Array v); + //void uniform1fv(WebGLUniformLocation? location, sequence<GLfloat> v); + //void uniform1i(WebGLUniformLocation? location, GLint x); + //void uniform1iv(WebGLUniformLocation? location, Int32Array v); + //void uniform1iv(WebGLUniformLocation? location, sequence<long> v); + //void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); + //void uniform2fv(WebGLUniformLocation? location, Float32Array v); + //void uniform2fv(WebGLUniformLocation? location, sequence<GLfloat> v); + //void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); + //void uniform2iv(WebGLUniformLocation? location, Int32Array v); + //void uniform2iv(WebGLUniformLocation? location, sequence<long> v); + //void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); + //void uniform3fv(WebGLUniformLocation? location, Float32Array v); + //void uniform3fv(WebGLUniformLocation? location, sequence<GLfloat> v); + //void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); + //void uniform3iv(WebGLUniformLocation? location, Int32Array v); + //void uniform3iv(WebGLUniformLocation? location, sequence<long> v); + //void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + //void uniform4fv(WebGLUniformLocation? location, Float32Array v); + //void uniform4fv(WebGLUniformLocation? location, sequence<GLfloat> v); + //void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); + //void uniform4iv(WebGLUniformLocation? location, Int32Array v); + //void uniform4iv(WebGLUniformLocation? location, sequence<long> v); + + //void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, + // Float32Array value); + //void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, + // sequence<GLfloat> value); + //void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, + // Float32Array value); + //void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, + // sequence<GLfloat> value); + //void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, + // Float32Array value); + //void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, + // sequence<GLfloat> value); + + //void useProgram(WebGLProgram? program); + //void validateProgram(WebGLProgram? program); + + //void vertexAttrib1f(GLuint indx, GLfloat x); + //void vertexAttrib1fv(GLuint indx, Float32Array values); + //void vertexAttrib1fv(GLuint indx, sequence<GLfloat> values); + //void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); + //void vertexAttrib2fv(GLuint indx, Float32Array values); + //void vertexAttrib2fv(GLuint indx, sequence<GLfloat> values); + //void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + //void vertexAttrib3fv(GLuint indx, Float32Array values); + //void vertexAttrib3fv(GLuint indx, sequence<GLfloat> values); + //void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + //void vertexAttrib4fv(GLuint indx, Float32Array values); + //void vertexAttrib4fv(GLuint indx, sequence<GLfloat> values); + //void vertexAttribPointer(GLuint indx, GLint size, GLenum type, + // GLboolean normalized, GLsizei stride, GLintptr offset); + + //void viewport(GLint x, GLint y, GLsizei width, GLsizei height); +}; + +interface WebGLRenderingContext +{ +}; +WebGLRenderingContext implements WebGLRenderingContextBase; + + +//[Constructor(DOMString type, optional WebGLContextEventInit eventInit)] +//interface WebGLContextEvent : Event { +// readonly attribute DOMString statusMessage; +//}; + +// EventInit is defined in the DOM4 specification. +//dictionary WebGLContextEventInit : EventInit { +// DOMString statusMessage; +//}; diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl index a259729f691..8999d9e561d 100644 --- a/components/script/dom/webidls/Window.webidl +++ b/components/script/dom/webidls/Window.webidl @@ -128,14 +128,14 @@ partial interface Window { }; Window implements OnErrorEventHandlerForWindow; -// https://html.spec.whatwg.org/multipage/webstorage.html#dom-sessionstorage +// https://html.spec.whatwg.org/multipage/#dom-sessionstorage [NoInterfaceObject] interface WindowSessionStorage { readonly attribute Storage sessionStorage; }; Window implements WindowSessionStorage; -// https://html.spec.whatwg.org/multipage/webstorage.html#dom-localstorage +// https://html.spec.whatwg.org/multipage/#dom-localstorage [NoInterfaceObject] interface WindowLocalStorage { readonly attribute Storage localStorage; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index f4e2f5b0732..b46a5af952d 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -29,7 +29,7 @@ use dom::storage::Storage; use layout_interface::{ReflowGoal, ReflowQueryType, LayoutRPC, LayoutChan, Reflow, Msg}; use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ScriptReflow}; use page::Page; -use script_task::{TimerSource, ScriptChan}; +use script_task::{TimerSource, ScriptChan, ScriptPort, NonWorkerScriptChan}; use script_task::ScriptMsg; use script_traits::ScriptControlChan; use timers::{IsInterval, TimerId, TimerManager, TimerCallback}; @@ -198,6 +198,11 @@ impl Window { self.parent_info } + pub fn new_script_pair(&self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) { + let (tx, rx) = channel(); + (box NonWorkerScriptChan(tx), box rx) + } + pub fn control_chan<'a>(&'a self) -> &'a ScriptControlChan { &self.control_chan } diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 1da422c79e0..e80d5529115 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -35,7 +35,7 @@ use std::sync::mpsc::{channel, Sender}; pub type TrustedWorkerAddress = Trusted<Worker>; -// https://html.spec.whatwg.org/multipage/workers.html#worker +// https://html.spec.whatwg.org/multipage/#worker #[dom_struct] pub struct Worker { eventtarget: EventTarget, diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 76fd85e0603..bbb81f369dd 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -16,7 +16,7 @@ use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::workerlocation::WorkerLocation; use dom::workernavigator::WorkerNavigator; use dom::window::{base64_atob, base64_btoa}; -use script_task::{ScriptChan, TimerSource}; +use script_task::{ScriptChan, TimerSource, ScriptPort, ScriptMsg}; use timers::{IsInterval, TimerId, TimerManager, TimerCallback}; use devtools_traits::DevtoolsControlChan; @@ -40,7 +40,7 @@ pub enum WorkerGlobalScopeTypeId { DedicatedGlobalScope, } -// https://html.spec.whatwg.org/multipage/workers.html#the-workerglobalscope-common-interface +// https://html.spec.whatwg.org/multipage/#the-workerglobalscope-common-interface #[dom_struct] pub struct WorkerGlobalScope { eventtarget: EventTarget, @@ -105,19 +105,19 @@ impl WorkerGlobalScope { } impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> { - // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-self + // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-self fn Self_(self) -> Temporary<WorkerGlobalScope> { Temporary::from_rooted(self) } - // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-location + // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-location fn Location(self) -> Temporary<WorkerLocation> { self.location.or_init(|| { WorkerLocation::new(self, self.worker_url.clone()) }) } - // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-importscripts + // https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-importscripts fn ImportScripts(self, url_strings: Vec<DOMString>) -> ErrorResult { let mut urls = Vec::with_capacity(url_strings.len()); for url in url_strings.into_iter() { @@ -150,7 +150,7 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> { Ok(()) } - // https://html.spec.whatwg.org/multipage/workers.html#dom-worker-navigator + // https://html.spec.whatwg.org/multipage/#dom-worker-navigator fn Navigator(self) -> Temporary<WorkerNavigator> { self.navigator.or_init(|| WorkerNavigator::new(self)) } @@ -216,6 +216,8 @@ pub trait WorkerGlobalScopeHelpers { fn handle_fire_timer(self, timer_id: TimerId); fn script_chan(self) -> Box<ScriptChan+Send>; fn pipeline(self) -> PipelineId; + fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>); + fn process_event(self, msg: ScriptMsg); fn get_cx(self) -> *mut JSContext; } @@ -238,6 +240,24 @@ impl<'a> WorkerGlobalScopeHelpers for JSRef<'a, WorkerGlobalScope> { } } + fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>) { + let dedicated: Option<JSRef<DedicatedWorkerGlobalScope>> = + DedicatedWorkerGlobalScopeCast::to_ref(self); + match dedicated { + Some(dedicated) => dedicated.new_script_pair(), + None => panic!("need to implement creating isolated event loops for SharedWorker"), + } + } + + fn process_event(self, msg: ScriptMsg) { + let dedicated: Option<JSRef<DedicatedWorkerGlobalScope>> = + DedicatedWorkerGlobalScopeCast::to_ref(self); + match dedicated { + Some(dedicated) => dedicated.process_event(msg), + None => panic!("need to implement processing single events for SharedWorker"), + } + } + fn handle_fire_timer(self, timer_id: TimerId) { self.timers.fire_timer(timer_id, self); } diff --git a/components/script/dom/workerlocation.rs b/components/script/dom/workerlocation.rs index 0d82fc79098..c8aa09cd750 100644 --- a/components/script/dom/workerlocation.rs +++ b/components/script/dom/workerlocation.rs @@ -13,7 +13,7 @@ use dom::workerglobalscope::WorkerGlobalScope; use url::Url; -// https://html.spec.whatwg.org/multipage/workers.html#worker-locations +// https://html.spec.whatwg.org/multipage/#worker-locations #[dom_struct] pub struct WorkerLocation { reflector_: Reflector, diff --git a/components/script/dom/workernavigator.rs b/components/script/dom/workernavigator.rs index ea446f986cb..6a6a325ae39 100644 --- a/components/script/dom/workernavigator.rs +++ b/components/script/dom/workernavigator.rs @@ -11,7 +11,7 @@ use dom::navigatorinfo; use dom::workerglobalscope::WorkerGlobalScope; use util::str::DOMString; -// https://html.spec.whatwg.org/multipage/workers.html#workernavigator +// https://html.spec.whatwg.org/multipage/#workernavigator #[dom_struct] pub struct WorkerNavigator { reflector_: Reflector, diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 5d0f76e5463..a4e9e767dd5 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -26,7 +26,8 @@ use dom::urlsearchparams::URLSearchParamsHelpers; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId; use dom::xmlhttprequestupload::XMLHttpRequestUpload; -use script_task::{ScriptChan, ScriptMsg, Runnable}; +use network_listener::{NetworkListener, PreInvoke}; +use script_task::{ScriptChan, ScriptMsg, Runnable, ScriptPort}; use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; @@ -43,19 +44,20 @@ use js::jsapi::JS_ClearPendingException; use js::jsval::{JSVal, NullValue, UndefinedValue}; use net_traits::ControlMsg::Load; -use net_traits::ProgressMsg::{Payload, Done}; -use net_traits::{ResourceTask, ResourceCORSData, LoadData, LoadResponse}; -use cors::{allow_cross_origin_request, CORSRequest, RequestMode}; +use net_traits::{ResourceTask, ResourceCORSData, LoadData, LoadConsumer}; +use net_traits::{AsyncResponseListener, Metadata}; +use cors::{allow_cross_origin_request, CORSRequest, RequestMode, AsyncCORSResponseListener}; +use cors::CORSResponse; use util::str::DOMString; use util::task::spawn_named; use std::ascii::AsciiExt; use std::borrow::ToOwned; -use std::cell::Cell; -use std::sync::mpsc::{Sender, Receiver, channel}; +use std::cell::{RefCell, Cell}; use std::default::Default; use std::old_io::Timer; use std::str::FromStr; +use std::sync::{Mutex, Arc}; use std::time::duration::Duration; use time; use url::{Url, UrlParser}; @@ -74,28 +76,20 @@ enum XMLHttpRequestState { Done = 4, } -struct XHRProgressHandler { - addr: TrustedXHRAddress, - progress: XHRProgress, -} - -impl XHRProgressHandler { - fn new(addr: TrustedXHRAddress, progress: XHRProgress) -> XHRProgressHandler { - XHRProgressHandler { addr: addr, progress: progress } - } -} - -impl Runnable for XHRProgressHandler { - fn handler(self: Box<XHRProgressHandler>) { - let this = *self; - XMLHttpRequest::handle_progress(this.addr, this.progress); - } -} - #[derive(PartialEq, Clone, Copy)] #[jstraceable] pub struct GenerationId(u32); +/// Closure of required data for each async network event that comprises the +/// XHR's response. +struct XHRContext { + xhr: TrustedXHRAddress, + gen_id: GenerationId, + cors_request: Option<CORSRequest>, + buf: DOMRefCell<Vec<u8>>, + sync_status: DOMRefCell<Option<ErrorResult>>, +} + #[derive(Clone)] pub enum XHRProgress { /// Notify that headers have been received @@ -119,16 +113,6 @@ impl XHRProgress { } } -enum SyncOrAsync<'a> { - Sync(JSRef<'a, XMLHttpRequest>), - Async(TrustedXHRAddress, Box<ScriptChan+Send>) -} - -enum TerminateReason { - AbortedOrReopened, - TimedOut, -} - #[dom_struct] pub struct XMLHttpRequest { eventtarget: XMLHttpRequestEventTarget, @@ -157,8 +141,9 @@ pub struct XMLHttpRequest { global: GlobalField, timer: DOMRefCell<Timer>, fetch_time: Cell<i64>, - terminate_sender: DOMRefCell<Option<Sender<TerminateReason>>>, + timeout_target: DOMRefCell<Option<Box<ScriptChan+Send>>>, generation_id: Cell<GenerationId>, + response_status: Cell<Result<(), ()>>, } impl XMLHttpRequest { @@ -190,8 +175,9 @@ impl XMLHttpRequest { global: GlobalField::from_rooted(&global), timer: DOMRefCell::new(Timer::new().unwrap()), fetch_time: Cell::new(0), - terminate_sender: DOMRefCell::new(None), - generation_id: Cell::new(GenerationId(0)) + timeout_target: DOMRefCell::new(None), + generation_id: Cell::new(GenerationId(0)), + response_status: Cell::new(Ok(())), } } pub fn new(global: GlobalRef) -> Temporary<XMLHttpRequest> { @@ -205,141 +191,91 @@ impl XMLHttpRequest { Ok(XMLHttpRequest::new(global)) } - pub fn handle_progress(addr: TrustedXHRAddress, progress: XHRProgress) { - let xhr = addr.to_temporary().root(); - xhr.r().process_partial_response(progress); - } - - #[allow(unsafe_code)] - fn fetch(fetch_type: &SyncOrAsync, resource_task: ResourceTask, - mut load_data: LoadData, terminate_receiver: Receiver<TerminateReason>, - cors_request: Result<Option<CORSRequest>,()>, gen_id: GenerationId, - start_port: Receiver<LoadResponse>) -> ErrorResult { - - fn notify_partial_progress(fetch_type: &SyncOrAsync, msg: XHRProgress) { - match *fetch_type { - SyncOrAsync::Sync(xhr) => { - xhr.process_partial_response(msg); - }, - SyncOrAsync::Async(ref addr, ref script_chan) => { - script_chan.send(ScriptMsg::RunnableMsg(box XHRProgressHandler::new(addr.clone(), msg))).unwrap(); - } - } + fn check_cors(context: Arc<Mutex<XHRContext>>, + load_data: LoadData, + req: CORSRequest, + script_chan: Box<ScriptChan+Send>, + resource_task: ResourceTask) { + struct CORSContext { + xhr: Arc<Mutex<XHRContext>>, + load_data: RefCell<Option<LoadData>>, + req: CORSRequest, + script_chan: Box<ScriptChan+Send>, + resource_task: ResourceTask, } - macro_rules! notify_error_and_return( - ($err:expr) => ({ - notify_partial_progress(fetch_type, XHRProgress::Errored(gen_id, $err)); - return Err($err) - }); - ); - - macro_rules! terminate( - ($reason:expr) => ( - match $reason { - TerminateReason::AbortedOrReopened => { - return Err(Abort) - } - TerminateReason::TimedOut => { - notify_error_and_return!(Timeout); - } + impl AsyncCORSResponseListener for CORSContext { + fn response_available(&self, response: CORSResponse) { + if response.network_error { + let mut context = self.xhr.lock().unwrap(); + let xhr = context.xhr.to_temporary().root(); + xhr.r().process_partial_response(XHRProgress::Errored(context.gen_id, Network)); + *context.sync_status.borrow_mut() = Some(Err(Network)); + return; } - ); - ); - - - match cors_request { - Err(_) => { - // Happens in case of cross-origin non-http URIs - notify_error_and_return!(Network); - } - Ok(Some(ref req)) => { - let (chan, cors_port) = channel(); - let req2 = req.clone(); - // TODO: this exists only to make preflight check non-blocking - // perhaps should be handled by the resource_loader? - spawn_named("XHR:Cors".to_owned(), move || { - let response = req2.http_fetch(); - chan.send(response).unwrap(); + let mut load_data = self.load_data.borrow_mut().take().unwrap(); + load_data.cors = Some(ResourceCORSData { + preflight: self.req.preflight_flag, + origin: self.req.origin.clone() }); - select! ( - response = cors_port.recv() => { - let response = response.unwrap(); - if response.network_error { - notify_error_and_return!(Network); - } else { - load_data.cors = Some(ResourceCORSData { - preflight: req.preflight_flag, - origin: req.origin.clone() - }); - } - }, - reason = terminate_receiver.recv() => terminate!(reason.unwrap()) - ); + XMLHttpRequest::initiate_async_xhr(self.xhr.clone(), self.script_chan.clone(), + self.resource_task.clone(), load_data); } - _ => {} } - // Step 10, 13 - resource_task.send(Load(load_data)).unwrap(); + let cors_context = CORSContext { + xhr: context, + load_data: RefCell::new(Some(load_data)), + req: req.clone(), + script_chan: script_chan.clone(), + resource_task: resource_task, + }; + req.http_fetch_async(box cors_context, script_chan); + } - let progress_port; - select! ( - response = start_port.recv() => { - let response = response.unwrap(); - match cors_request { - Ok(Some(ref req)) => { - match response.metadata.headers { - Some(ref h) if allow_cross_origin_request(req, h) => {}, - _ => notify_error_and_return!(Network) - } - }, + fn initiate_async_xhr(context: Arc<Mutex<XHRContext>>, + script_chan: Box<ScriptChan+Send>, + resource_task: ResourceTask, + load_data: LoadData) { + impl AsyncResponseListener for XHRContext { + fn headers_available(&self, metadata: Metadata) { + let xhr = self.xhr.to_temporary().root(); + let rv = xhr.r().process_headers_available(self.cors_request.clone(), + self.gen_id, + metadata); + if rv.is_err() { + *self.sync_status.borrow_mut() = Some(rv); + } + } - _ => {} - }; - // XXXManishearth Clear cache entries in case of a network error - notify_partial_progress(fetch_type, XHRProgress::HeadersReceived(gen_id, - response.metadata.headers.clone(), response.metadata.status.clone())); + fn data_available(&self, payload: Vec<u8>) { + self.buf.borrow_mut().push_all(payload.as_slice()); + let xhr = self.xhr.to_temporary().root(); + xhr.r().process_data_available(self.gen_id, self.buf.borrow().clone()); + } - progress_port = response.progress_port; - }, - reason = terminate_receiver.recv() => terminate!(reason.unwrap()) - ); + fn response_complete(&self, status: Result<(), String>) { + let xhr = self.xhr.to_temporary().root(); + let rv = xhr.r().process_response_complete(self.gen_id, status); + *self.sync_status.borrow_mut() = Some(rv); + } + } - let mut buf = vec!(); - loop { - // Under most circumstances, progress_port will contain lots of Payload - // events. Since select! does not have any fairness or priority, it - // might always remove the progress_port event, even when there is - // a terminate event waiting in the terminate_receiver. If this happens, - // a timeout or abort will take too long to be processed. To avoid this, - // in each iteration, we check for a terminate event before we block. - match terminate_receiver.try_recv() { - Ok(reason) => terminate!(reason), - Err(_) => () - }; - - select! ( - progress = progress_port.recv() => match progress.unwrap() { - Payload(data) => { - buf.push_all(data.as_slice()); - notify_partial_progress(fetch_type, - XHRProgress::Loading(gen_id, ByteString::new(buf.clone()))); - }, - Done(Ok(())) => { - notify_partial_progress(fetch_type, XHRProgress::Done(gen_id)); - return Ok(()); - }, - Done(Err(_)) => { - notify_error_and_return!(Network); - } - }, - reason = terminate_receiver.recv() => terminate!(reason.unwrap()) - ); + impl PreInvoke for XHRContext { + fn should_invoke(&self) -> bool { + let xhr = self.xhr.to_temporary().root(); + xhr.r().generation_id.get() == self.gen_id + } } + + let listener = box NetworkListener { + context: context, + script_chan: script_chan, + }; + resource_task.send(Load(load_data, LoadConsumer::Listener(listener))).unwrap(); } } @@ -577,10 +513,7 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> { } - let global = self.global.root(); - let resource_task = global.r().resource_task(); - let (start_chan, start_port) = channel(); - let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap(), start_chan); + let mut load_data = LoadData::new(self.request_url.borrow().clone().unwrap()); load_data.data = extracted; #[inline] @@ -613,10 +546,9 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> { } load_data.method = (*self.request_method.borrow()).clone(); - let (terminate_sender, terminate_receiver) = channel(); - *self.terminate_sender.borrow_mut() = Some(terminate_sender); // CORS stuff + let global = self.global.root(); let referer_url = self.global.root().r().get_url(); let mode = if self.upload_events.get() { RequestMode::ForcedPreflight @@ -647,31 +579,15 @@ impl<'a> XMLHttpRequestMethods for JSRef<'a, XMLHttpRequest> { debug!("request_headers = {:?}", *self.request_headers.borrow()); - let gen_id = self.generation_id.get(); + self.fetch_time.set(time::now().to_timespec().sec); + let rv = self.fetch(load_data, cors_request, global.r()); if self.sync.get() { - return XMLHttpRequest::fetch(&mut SyncOrAsync::Sync(self), resource_task, load_data, - terminate_receiver, cors_request, gen_id, start_port); - } else { - self.fetch_time.set(time::now().to_timespec().sec); - let script_chan = global.r().script_chan(); - // Pin the object before launching the fetch task. This is to ensure that - // the object will stay alive as long as there are (possibly cancelled) - // inflight events queued up in the script task's port. - let addr = Trusted::new(self.global.root().r().get_cx(), self, - script_chan.clone()); - spawn_named("XHRTask".to_owned(), move || { - let _ = XMLHttpRequest::fetch(&mut SyncOrAsync::Async(addr, script_chan), - resource_task, - load_data, - terminate_receiver, - cors_request, - gen_id, - start_port); - }); - let timeout = self.timeout.get(); - if timeout > 0 { - self.set_timeout(timeout); - } + return rv; + } + + let timeout = self.timeout.get(); + if timeout > 0 { + self.set_timeout(timeout); } Ok(()) } @@ -812,6 +728,10 @@ pub type TrustedXHRAddress = Trusted<XMLHttpRequest>; trait PrivateXMLHttpRequestHelpers { fn change_ready_state(self, XMLHttpRequestState); + fn process_headers_available(&self, cors_request: Option<CORSRequest>, + gen_id: GenerationId, metadata: Metadata) -> Result<(), Error>; + fn process_data_available(self, gen_id: GenerationId, payload: Vec<u8>); + fn process_response_complete(self, gen_id: GenerationId, status: Result<(), String>) -> ErrorResult; fn process_partial_response(self, progress: XHRProgress); fn terminate_ongoing_fetch(self); fn insert_trusted_header(self, name: String, value: String); @@ -822,6 +742,9 @@ trait PrivateXMLHttpRequestHelpers { fn set_timeout(self, timeout:u32); fn cancel_timeout(self); fn filter_response_headers(self) -> Headers; + fn discard_subsequent_responses(self); + fn fetch(self, load_data: LoadData, cors_request: Result<Option<CORSRequest>,()>, + global: GlobalRef) -> ErrorResult; } impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { @@ -837,6 +760,45 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { event.r().fire(target); } + fn process_headers_available(&self, cors_request: Option<CORSRequest>, + gen_id: GenerationId, metadata: Metadata) -> Result<(), Error> { + match cors_request { + Some(ref req) => { + match metadata.headers { + Some(ref h) if allow_cross_origin_request(req, h) => {}, + _ => { + self.process_partial_response(XHRProgress::Errored(gen_id, Network)); + return Err(Network); + } + } + }, + + _ => {} + }; + // XXXManishearth Clear cache entries in case of a network error + self.process_partial_response(XHRProgress::HeadersReceived(gen_id, + metadata.headers, metadata.status)); + Ok(()) + } + + fn process_data_available(self, gen_id: GenerationId, payload: Vec<u8>) { + self.process_partial_response(XHRProgress::Loading(gen_id, ByteString::new(payload))); + } + + fn process_response_complete(self, gen_id: GenerationId, status: Result<(), String>) + -> ErrorResult { + match status { + Ok(()) => { + self.process_partial_response(XHRProgress::Done(gen_id)); + Ok(()) + }, + Err(_) => { + self.process_partial_response(XHRProgress::Errored(gen_id, Network)); + Err(Network) + } + } + } + fn process_partial_response(self, progress: XHRProgress) { let msg_id = progress.generation_id(); @@ -853,6 +815,11 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { // Ignore message if it belongs to a terminated fetch return_if_fetch_was_terminated!(); + // Ignore messages coming from previously-errored responses or requests that have timed out + if self.response_status.get().is_err() { + return; + } + match progress { XHRProgress::HeadersReceived(_, headers, status) => { assert!(self.ready_state.get() == XMLHttpRequestState::Opened); @@ -904,6 +871,8 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { self.ready_state.get() == XMLHttpRequestState::Loading || self.sync.get()); + self.cancel_timeout(); + // Part of step 11, send() (processing response end of file) // XXXManishearth handle errors, if any (substep 2) @@ -919,6 +888,9 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { self.dispatch_response_progress_event("loadend".to_owned()); }, XHRProgress::Errored(_, e) => { + self.cancel_timeout(); + + self.discard_subsequent_responses(); self.send_flag.set(false); // XXXManishearth set response to NetworkError self.change_ready_state(XMLHttpRequestState::Done); @@ -952,7 +924,8 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { fn terminate_ongoing_fetch(self) { let GenerationId(prev_id) = self.generation_id.get(); self.generation_id.set(GenerationId(prev_id + 1)); - self.terminate_sender.borrow().as_ref().map(|s| s.send(TerminateReason::AbortedOrReopened)); + *self.timeout_target.borrow_mut() = None; + self.response_status.set(Ok(())); } fn insert_trusted_header(self, name: String, value: String) { @@ -990,15 +963,36 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { self.dispatch_progress_event(false, type_, len, total); } fn set_timeout(self, timeout: u32) { + struct XHRTimeout { + xhr: TrustedXHRAddress, + gen_id: GenerationId, + } + + impl Runnable for XHRTimeout { + fn handler(self: Box<XHRTimeout>) { + let this = *self; + let xhr = this.xhr.to_temporary().root(); + if xhr.r().ready_state.get() != XMLHttpRequestState::Done { + xhr.r().process_partial_response(XHRProgress::Errored(this.gen_id, Timeout)); + } + } + } + // Sets up the object to timeout in a given number of milliseconds // This will cancel all previous timeouts let oneshot = self.timer.borrow_mut() .oneshot(Duration::milliseconds(timeout as i64)); - let terminate_sender = (*self.terminate_sender.borrow()).clone(); + let timeout_target = (*self.timeout_target.borrow().as_ref().unwrap()).clone(); + let global = self.global.root(); + let xhr = Trusted::new(global.r().get_cx(), self, global.r().script_chan()); + let gen_id = self.generation_id.get(); spawn_named("XHR:Timer".to_owned(), move || { match oneshot.recv() { Ok(_) => { - terminate_sender.map(|s| s.send(TerminateReason::TimedOut)); + timeout_target.send(ScriptMsg::RunnableMsg(box XHRTimeout { + xhr: xhr, + gen_id: gen_id, + })).unwrap(); }, Err(_) => { // This occurs if xhr.timeout (the sender) goes out of scope (i.e, xhr went out of scope) @@ -1065,6 +1059,64 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { // XXXManishearth additional CORS filtering goes here headers } + + fn discard_subsequent_responses(self) { + self.response_status.set(Err(())); + } + + fn fetch(self, + load_data: LoadData, + cors_request: Result<Option<CORSRequest>,()>, + global: GlobalRef) -> ErrorResult { + let cors_request = match cors_request { + Err(_) => { + // Happens in case of cross-origin non-http URIs + self.process_partial_response(XHRProgress::Errored( + self.generation_id.get(), Network)); + return Err(Network); + } + Ok(req) => req, + }; + + let xhr = Trusted::new(global.get_cx(), self, global.script_chan()); + + let context = Arc::new(Mutex::new(XHRContext { + xhr: xhr, + cors_request: cors_request.clone(), + gen_id: self.generation_id.get(), + buf: DOMRefCell::new(vec!()), + sync_status: DOMRefCell::new(None), + })); + + let (script_chan, script_port) = if self.sync.get() { + let (tx, rx) = global.new_script_pair(); + (tx, Some(rx)) + } else { + (global.script_chan(), None) + }; + *self.timeout_target.borrow_mut() = Some(script_chan.clone()); + + let resource_task = global.resource_task(); + if let Some(req) = cors_request { + XMLHttpRequest::check_cors(context.clone(), load_data, req.clone(), + script_chan.clone(), resource_task); + } else { + XMLHttpRequest::initiate_async_xhr(context.clone(), script_chan, + resource_task, load_data); + } + + if let Some(script_port) = script_port { + loop { + global.process_event(script_port.recv()); + let context = context.lock().unwrap(); + let sync_status = context.sync_status.borrow(); + if let Some(ref status) = *sync_status { + return status.clone(); + } + } + } + Ok(()) + } } trait Extractable { diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index d04acc36c67..4859c075058 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -178,7 +178,7 @@ impl ScriptLayoutChan for OpaqueScriptLayoutChannel { pub type OpaqueNode = uintptr_t; /// State relating to an animation. -#[derive(Copy, Clone)] +#[derive(Clone)] pub struct Animation { /// An opaque reference to the DOM node participating in the animation. pub node: OpaqueNode, diff --git a/components/script/lib.rs b/components/script/lib.rs index 4a9fcdbd09c..b9f4b42f84d 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -61,6 +61,7 @@ pub mod dom; pub mod parse; pub mod layout_interface; +mod network_listener; pub mod page; pub mod script_task; mod timers; diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs new file mode 100644 index 00000000000..5f400eb76b3 --- /dev/null +++ b/components/script/network_listener.rs @@ -0,0 +1,48 @@ +/* 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 script_task::{ScriptChan, ScriptMsg, Runnable}; +use net_traits::{AsyncResponseTarget, AsyncResponseListener, ResponseAction}; +use std::sync::{Arc, Mutex}; + +/// An off-thread sink for async network event runnables. All such events are forwarded to +/// a target thread, where they are invoked on the provided context object. +pub struct NetworkListener<T: AsyncResponseListener + PreInvoke + Send + 'static> { + pub context: Arc<Mutex<T>>, + pub script_chan: Box<ScriptChan+Send>, +} + +impl<T: AsyncResponseListener + PreInvoke + Send + 'static> AsyncResponseTarget for NetworkListener<T> { + fn invoke_with_listener(&self, action: ResponseAction) { + self.script_chan.send(ScriptMsg::RunnableMsg(box ListenerRunnable { + context: self.context.clone(), + action: action, + })).unwrap(); + } +} + +/// A gating mechanism that runs before invoking the runnable on the target thread. +/// If the `should_invoke` method returns false, the runnable is discarded without +/// being invoked. +pub trait PreInvoke { + fn should_invoke(&self) -> bool { + true + } +} + +/// A runnable for moving the async network events between threads. +struct ListenerRunnable<T: AsyncResponseListener + PreInvoke + Send> { + context: Arc<Mutex<T>>, + action: ResponseAction, +} + +impl<T: AsyncResponseListener + PreInvoke + Send> Runnable for ListenerRunnable<T> { + fn handler(self: Box<ListenerRunnable<T>>) { + let this = *self; + let context = this.context.lock().unwrap(); + if context.should_invoke() { + this.action.process(&*context); + } + } +} diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs index 5fb99174591..1424c72181c 100644 --- a/components/script/parse/html.rs +++ b/components/script/parse/html.rs @@ -275,7 +275,7 @@ pub fn parse_html(document: JSRef<Document>, task_state::enter(IN_HTML_PARSER); } - fn parse_progress(parser: &JSRef<ServoHTMLParser>, url: &Url, load_response: &LoadResponse) { + fn parse_progress(parser: JSRef<ServoHTMLParser>, url: &Url, load_response: &LoadResponse) { for msg in load_response.progress_port.iter() { match msg { ProgressMsg::Payload(data) => { @@ -314,10 +314,10 @@ pub fn parse_html(document: JSRef<Document>, // https://html.spec.whatwg.org/multipage/#read-text let page = format!("<pre>\u{000A}<plaintext>"); parser.parse_chunk(page); - parse_progress(&parser, url, &load_response); + parse_progress(parser, url, &load_response); }, _ => { - parse_progress(&parser, url, &load_response); + parse_progress(parser, url, &load_response); } } } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 877289a27fd..92a5dccb7d4 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -24,20 +24,21 @@ use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, Documen use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast}; use dom::bindings::conversions::FromJSValConvertible; use dom::bindings::conversions::StringificationBehavior; -use dom::bindings::js::{JS, JSRef, OptionalRootable, RootedReference}; +use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, RootedReference}; use dom::bindings::js::{RootCollection, RootCollectionPtr}; use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference}; use dom::bindings::structuredclone::StructuredCloneData; -use dom::bindings::trace::{JSTraceable, trace_collections}; +use dom::bindings::trace::{JSTraceable, trace_collections, RootedVec}; use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap}; use dom::document::{Document, IsHTMLDocument, DocumentHelpers, DocumentProgressHandler, DocumentProgressTask, DocumentSource}; use dom::element::{Element, AttributeHandlers}; use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable}; -use dom::htmliframeelement::HTMLIFrameElementHelpers; +use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementHelpers}; use dom::uievent::UIEvent; use dom::eventtarget::EventTarget; use dom::node::{self, Node, NodeHelpers, NodeDamage, window_from_node}; use dom::window::{Window, WindowHelpers, ScriptHelpers, ReflowReason}; +use dom::worker::TrustedWorkerAddress; use parse::html::{HTMLInput, parse_html}; use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowGoal, ReflowQueryType}; use layout_interface; @@ -57,11 +58,11 @@ use script_traits::{ConstellationControlMsg, ScriptControlChan}; use script_traits::ScriptTaskFactory; use msg::compositor_msg::ReadyState::{FinishedLoading, Loading, PerformingLayout}; use msg::compositor_msg::{LayerId, ScriptListener}; -use msg::constellation_msg::{ConstellationChan}; +use msg::constellation_msg::{ConstellationChan, FocusType}; use msg::constellation_msg::{LoadData, PipelineId, SubpageId, MozBrowserEvent, WorkerId}; use msg::constellation_msg::{Failure, WindowSizeData, PipelineExitType}; use msg::constellation_msg::Msg as ConstellationMsg; -use net_traits::{ResourceTask, ControlMsg, LoadResponse}; +use net_traits::{ResourceTask, ControlMsg, LoadResponse, LoadConsumer}; use net_traits::LoadData as NetLoadData; use net_traits::image_cache_task::ImageCacheTask; use net_traits::storage_task::StorageTask; @@ -200,6 +201,25 @@ pub trait ScriptChan { fn clone(&self) -> Box<ScriptChan+Send>; } +/// An interface for receiving ScriptMsg values in an event loop. Used for synchronous DOM +/// APIs that need to abstract over multiple kinds of event loops (worker/main thread) with +/// different Receiver interfaces. +pub trait ScriptPort { + fn recv(&self) -> ScriptMsg; +} + +impl ScriptPort for Receiver<ScriptMsg> { + fn recv(&self) -> ScriptMsg { + self.recv().unwrap() + } +} + +impl ScriptPort for Receiver<(TrustedWorkerAddress, ScriptMsg)> { + fn recv(&self) -> ScriptMsg { + self.recv().unwrap().1 + } +} + /// Encapsulates internal communication within the script task. #[jstraceable] pub struct NonWorkerScriptChan(pub Sender<ScriptMsg>); @@ -291,7 +311,7 @@ pub struct ScriptTask { /// The JavaScript runtime. js_runtime: js::rust::rt, /// The JSContext. - js_context: DOMRefCell<Option<Rc<Cx>>>, + js_context: Rc<Cx>, mouse_over_targets: DOMRefCell<Vec<JS<Node>>> } @@ -328,7 +348,6 @@ impl<'a> Drop for ScriptMemoryFailsafe<'a> { let window = page.window_for_script_deallocation(); (*window.unsafe_get()).clear_js_context_for_script_deallocation(); } - *owner.js_context.borrow_for_script_deallocation() = None; } } None => (), @@ -403,6 +422,15 @@ unsafe extern "C" fn debug_gc_callback(_rt: *mut JSRuntime, status: JSGCStatus) } impl ScriptTask { + pub fn process_event(msg: ScriptMsg) { + SCRIPT_TASK_ROOT.with(|root| { + if let Some(script_task) = *root.borrow() { + let script_task = unsafe { &*script_task }; + script_task.handle_msg_from_script(msg); + } + }); + } + /// Creates a new script task. pub fn new(compositor: Box<ScriptListener+'static>, port: Receiver<ScriptMsg>, @@ -459,7 +487,7 @@ impl ScriptTask { devtools_marker_sender: RefCell::new(None), js_runtime: js_runtime, - js_context: DOMRefCell::new(Some(js_context)), + js_context: js_context, mouse_over_targets: DOMRefCell::new(vec!()) } } @@ -489,7 +517,7 @@ impl ScriptTask { } pub fn get_cx(&self) -> *mut JSContext { - (**self.js_context.borrow().as_ref().unwrap()).ptr + self.js_context.ptr } /// Starts the script task. After calling this method, the script task will loop receiving @@ -665,6 +693,8 @@ impl ScriptTask { old_subpage_id, new_subpage_id) => self.handle_update_subpage_id(containing_pipeline_id, old_subpage_id, new_subpage_id), + ConstellationControlMsg::FocusIFrameMsg(containing_pipeline_id, subpage_id) => + self.handle_focus_iframe_msg(containing_pipeline_id, subpage_id), } } @@ -812,6 +842,23 @@ impl ScriptTask { window.r().thaw(); } + fn handle_focus_iframe_msg(&self, + parent_pipeline_id: PipelineId, + subpage_id: SubpageId) { + let borrowed_page = self.root_page(); + let page = borrowed_page.find(parent_pipeline_id).unwrap(); + + let doc = page.document().root(); + let frame_element = self.find_iframe(doc.r(), subpage_id).root(); + + if let Some(frame_element) = frame_element { + let element: JSRef<Element> = ElementCast::from_ref(frame_element.r()); + doc.r().begin_focus_transaction(); + doc.r().request_focus(element); + doc.r().commit_focus_transaction(FocusType::Parent); + } + } + /// Handles a mozbrowser event, for example see: /// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart fn handle_mozbrowser_event_msg(&self, @@ -822,11 +869,7 @@ impl ScriptTask { let frame_element = borrowed_page.find(parent_pipeline_id).and_then(|page| { let doc = page.document().root(); - let doc: JSRef<Node> = NodeCast::from_ref(doc.r()); - - doc.traverse_preorder() - .filter_map(HTMLIFrameElementCast::to_temporary) - .find(|node| node.root().r().subpage_id() == Some(subpage_id)) + self.find_iframe(doc.r(), subpage_id) }).root(); if let Some(frame_element) = frame_element { @@ -842,11 +885,7 @@ impl ScriptTask { let frame_element = borrowed_page.find(containing_pipeline_id).and_then(|page| { let doc = page.document().root(); - let doc: JSRef<Node> = NodeCast::from_ref(doc.r()); - - doc.traverse_preorder() - .filter_map(HTMLIFrameElementCast::to_temporary) - .find(|node| node.root().r().subpage_id() == Some(old_subpage_id)) + self.find_iframe(doc.r(), old_subpage_id) }).root(); frame_element.unwrap().r().update_subpage_id(new_subpage_id); @@ -922,10 +961,7 @@ impl ScriptTask { let window = page.window().root(); if window.r().pipeline() == id { debug!("shutting down layout for root page {:?}", id); - // To ensure the elements of the DOM tree remain usable (such as the window global), - // don't free the JS context until all interactions with it are finished. shut_down_layout(&page, exit_type); - *self.js_context.borrow_mut() = None; return true } @@ -961,21 +997,13 @@ impl ScriptTask { borrowed_page.as_ref().and_then(|borrowed_page| { borrowed_page.find(parent_id).and_then(|page| { let doc = page.document().root(); - let doc: JSRef<Node> = NodeCast::from_ref(doc.r()); - - doc.traverse_preorder() - .filter_map(HTMLIFrameElementCast::to_temporary) - .find(|node| node.root().r().subpage_id() == Some(subpage_id)) - .map(ElementCast::from_temporary) + self.find_iframe(doc.r(), subpage_id) }) }) }).root(); self.compositor.borrow_mut().set_ready_state(incomplete.pipeline_id, Loading); - let cx = self.js_context.borrow(); - let cx = cx.as_ref().unwrap(); - // Create a new frame tree entry. let page = Rc::new(Page::new(incomplete.pipeline_id, final_url.clone())); if !root_page_exists { @@ -1034,7 +1062,7 @@ impl ScriptTask { let mut page_remover = AutoPageRemover::new(self, page_to_remove); // Create the window and document objects. - let window = Window::new(cx.clone(), + let window = Window::new(self.js_context.clone(), page.clone(), self.chan.clone(), self.control_chan.clone(), @@ -1065,7 +1093,8 @@ impl ScriptTask { last_modified, DocumentSource::FromParser).root(); - window.r().init_browser_context(document.r(), frame_element.r()); + let frame_element = frame_element.r().map(|elem| ElementCast::from_ref(elem)); + window.r().init_browser_context(document.r(), frame_element); // Create the root frame page.set_frame(Some(Frame { @@ -1157,6 +1186,16 @@ impl ScriptTask { window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, reason); } + /// Find an iframe element in a provided document. + fn find_iframe(&self, doc: JSRef<Document>, subpage_id: SubpageId) + -> Option<Temporary<HTMLIFrameElement>> { + let doc: JSRef<Node> = NodeCast::from_ref(doc); + + doc.traverse_preorder() + .filter_map(HTMLIFrameElementCast::to_temporary) + .find(|node| node.root().r().subpage_id() == Some(subpage_id)) + } + /// This is the main entry point for receiving and dispatching DOM events. /// /// TODO: Actually perform DOM event dispatch. @@ -1214,9 +1253,11 @@ impl ScriptTask { } let page = get_page(&self.root_page(), pipeline_id); let document = page.document().root(); - let mouse_over_targets = &mut *self.mouse_over_targets.borrow_mut(); + let mut mouse_over_targets = RootedVec::new(); + mouse_over_targets.append(&mut *self.mouse_over_targets.borrow_mut()); - document.r().handle_mouse_move_event(self.js_runtime.ptr, point, mouse_over_targets); + document.r().handle_mouse_move_event(self.js_runtime.ptr, point, &mut mouse_over_targets); + *self.mouse_over_targets.borrow_mut() = mouse_over_targets.clone(); } KeyEvent(key, state, modifiers) => { @@ -1241,11 +1282,7 @@ impl ScriptTask { let borrowed_page = self.root_page(); let iframe = borrowed_page.find(pipeline_id).and_then(|page| { let doc = page.document().root(); - let doc: JSRef<Node> = NodeCast::from_ref(doc.r()); - - doc.traverse_preorder() - .filter_map(HTMLIFrameElementCast::to_temporary) - .find(|node| node.root().r().subpage_id() == Some(subpage_id)) + self.find_iframe(doc.r(), subpage_id) }).root(); if let Some(iframe) = iframe.r() { iframe.navigate_child_browsing_context(load_data.url); @@ -1331,8 +1368,7 @@ impl ScriptTask { preserved_headers: load_data.headers, data: load_data.data, cors: None, - consumer: input_chan, - })).unwrap(); + }, LoadConsumer::Channel(input_chan))).unwrap(); let load_response = input_port.recv().unwrap(); script_chan.send(ScriptMsg::PageFetchComplete(id, subpage, load_response)).unwrap(); diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 57ceb73f2b3..a21a6ae3d1f 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -74,6 +74,8 @@ pub enum ConstellationControlMsg { MozBrowserEventMsg(PipelineId, SubpageId, MozBrowserEvent), /// Updates the current subpage id of a given iframe UpdateSubpageId(PipelineId, SubpageId, SubpageId), + /// Set an iframe to be focused. Used when an element in an iframe gains focus. + FocusIFrameMsg(PipelineId, SubpageId), } /// The mouse button involved in the event. diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 153569455a3..21b1955664d 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -35,7 +35,7 @@ source = "git+https://github.com/tomaka/android-rs-glue#5a68056599fb498b0cf3715f [[package]] name = "azure" version = "0.1.0" -source = "git+https://github.com/servo/rust-azure#358fc5da081cf7d0618fae2d9d5582951beb791f" +source = "git+https://github.com/servo/rust-azure#3e5daf667a62f702dc16285e923464458bef785f" dependencies = [ "core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)", "core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)", @@ -61,6 +61,9 @@ dependencies = [ "cssparser 0.2.0 (git+https://github.com/servo/rust-cssparser)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)", "gfx 0.0.1", + "gleam 0.0.1 (git+https://github.com/servo/gleam)", + "glutin 0.0.7 (git+https://github.com/servo/glutin?branch=servo)", + "msg 0.0.1", "util 0.0.1", ] @@ -109,6 +112,7 @@ dependencies = [ "time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "webdriver_server 0.0.1", ] [[package]] @@ -363,7 +367,7 @@ dependencies = [ [[package]] name = "gleam" version = "0.0.1" -source = "git+https://github.com/servo/gleam#fb17a364f314a35a6d209e875b5e90a920d41e86" +source = "git+https://github.com/servo/gleam#70c5f2ea3ef3602277b7c380c24b504e42338056" dependencies = [ "gl_common 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -932,6 +936,7 @@ dependencies = [ "cssparser 0.2.0 (git+https://github.com/servo/rust-cssparser)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)", "gfx 0.0.1", + "hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "net 0.0.1", "net_traits 0.0.1", "profile 0.0.1", @@ -1003,7 +1008,7 @@ dependencies = [ [[package]] name = "webdriver" version = "0.0.1" -source = "git+https://github.com/jgraham/webdriver-rust.git#906806d51783b5caad89432bf8ce008f2f4968fc" +source = "git+https://github.com/jgraham/webdriver-rust.git#4f543416a269b9d0d7ee5332db489768c2a769dd" dependencies = [ "hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1016,6 +1021,11 @@ dependencies = [ name = "webdriver_server" version = "0.0.1" dependencies = [ + "msg 0.0.1", + "rustc-serialize 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "util 0.0.1", + "uuid 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "webdriver 0.0.1 (git+https://github.com/jgraham/webdriver-rust.git)", ] diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index 045b54da226..f8d3fa3aa3e 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -27,11 +27,6 @@ harness = false [dependencies.png] git = "https://github.com/servo/rust-png" -[[test]] -name = "contenttest" -path = "../../tests/contenttest.rs" -harness = false - [features] default = ["glutin_app", "window"] window = ["glutin_app/window"] diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 7b4423f608c..1be279d5528 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -104,10 +104,6 @@ impl Browser { devtools::start_server(port) }); - if let Some(port) = opts.webdriver_port { - webdriver_server::start_server(port); - } - // Create the constellation, which maintains the engine // pipelines, including the script and layout threads, as well // as the navigation context. @@ -118,6 +114,10 @@ impl Browser { mem_profiler_chan.clone(), shared_task_pool); + if let Some(port) = opts.webdriver_port { + webdriver_server::start_server(port, constellation_chan.clone()); + }; + // The compositor coordinates with the client window to create the final // rendered page and display it somewhere. let compositor = CompositorTask::create(window, diff --git a/components/style/animation.rs b/components/style/animation.rs index f1237c34650..06e073bf745 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -6,14 +6,29 @@ use properties::ComputedValues; use properties::longhands::transition_property::computed_value::TransitionProperty; use properties::longhands::transition_timing_function::computed_value::{StartEnd}; use properties::longhands::transition_timing_function::computed_value::{TransitionTimingFunction}; +use properties::longhands::z_index::computed_value::T as ZIndex; +use properties::longhands::visibility::computed_value::T as Visibility; +use properties::longhands::vertical_align::computed_value::T as VerticalAlign; +use properties::longhands::border_spacing::computed_value::T as BorderSpacing; +use properties::longhands::line_height::computed_value::T as LineHeight; +use properties::longhands::font_weight::computed_value::T as FontWeight; +use properties::longhands::clip::computed_value::ClipRect; +use properties::longhands::text_shadow::computed_value::TextShadow; +use properties::longhands::text_shadow::computed_value::T as TextShadowList; +use properties::longhands::background_position::computed_value::T as BackgroundPosition; use properties::longhands::transition_property; -use values::computed::{LengthOrPercentageOrAuto, Time}; +use values::computed::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, LengthOrPercentage, Length, Time}; +use values::CSSFloat; +use cssparser::{RGBA, Color}; use std::num::Float; +use std::cmp::Ordering; +use std::iter::repeat; +use std::num::FromPrimitive; use util::bezier::Bezier; use util::geometry::Au; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct PropertyAnimation { property: AnimatedProperty, timing_function: TransitionTimingFunction, @@ -62,28 +77,70 @@ impl PropertyAnimation { new_style: &mut ComputedValues) -> Option<PropertyAnimation> { let animation_style = new_style.get_animation(); - let animated_property = match transition_property { - TransitionProperty::All => { - panic!("Don't use `TransitionProperty::All` with \ - `PropertyAnimation::from_transition_property`!") - } - TransitionProperty::Top => { - AnimatedProperty::Top(old_style.get_positionoffsets().top, - new_style.get_positionoffsets().top) - } - TransitionProperty::Right => { - AnimatedProperty::Right(old_style.get_positionoffsets().right, - new_style.get_positionoffsets().right) - } - TransitionProperty::Bottom => { - AnimatedProperty::Bottom(old_style.get_positionoffsets().bottom, - new_style.get_positionoffsets().bottom) - } - TransitionProperty::Left => { - AnimatedProperty::Left(old_style.get_positionoffsets().left, - new_style.get_positionoffsets().left) - } - }; + macro_rules! match_transition { + ( $( [$name:ident; $structname:ident; $field:ident] ),* ) => { + match transition_property { + TransitionProperty::All => { + panic!("Don't use `TransitionProperty::All` with \ + `PropertyAnimation::from_transition_property`!") + } + $( + TransitionProperty::$name => { + AnimatedProperty::$name(old_style.$structname().$field, + new_style.$structname().$field) + } + )* + TransitionProperty::TextShadow => { + AnimatedProperty::TextShadow(old_style.get_effects().text_shadow.clone(), + new_style.get_effects().text_shadow.clone()) + } + } + } + } + let animated_property = match_transition!( + [BackgroundColor; get_background; background_color], + [BackgroundPosition; get_background; background_position], + [BorderBottomColor; get_border; border_bottom_color], + [BorderBottomWidth; get_border; border_bottom_width], + [BorderLeftColor; get_border; border_left_color], + [BorderLeftWidth; get_border; border_left_width], + [BorderRightColor; get_border; border_right_color], + [BorderRightWidth; get_border; border_right_width], + [BorderSpacing; get_inheritedtable; border_spacing], + [BorderTopColor; get_border; border_top_color], + [BorderTopWidth; get_border; border_top_width], + [Bottom; get_positionoffsets; bottom], + [Color; get_color; color], + [Clip; get_effects; clip], + [FontSize; get_font; font_size], + [FontWeight; get_font; font_weight], + [Height; get_box; height], + [Left; get_positionoffsets; bottom], + [LetterSpacing; get_inheritedtext; letter_spacing], + [LineHeight; get_inheritedbox; line_height], + [MarginBottom; get_margin; margin_bottom], + [MarginLeft; get_margin; margin_left], + [MarginRight; get_margin; margin_right], + [MarginTop; get_margin; margin_top], + [MaxHeight; get_box; max_height], + [MaxWidth; get_box; max_width], + [MinHeight; get_box; min_height], + [MinWidth; get_box; min_width], + [Opacity; get_effects; opacity], + [OutlineColor; get_outline; outline_color], + [OutlineWidth; get_outline; outline_width], + [PaddingBottom; get_margin; margin_bottom], + [PaddingLeft; get_margin; margin_left], + [PaddingRight; get_margin; margin_right], + [PaddingTop; get_margin; margin_top], + [Right; get_positionoffsets; right], + [TextIndent; get_inheritedtext; text_indent], + [Top; get_positionoffsets; top], + [VerticalAlign; get_box; vertical_align], + [Visibility; get_inheritedbox; visibility], + [Width; get_box; width], + [WordSpacing; get_inheritedtext; word_spacing], + [ZIndex; get_box; z_index]); let property_animation = PropertyAnimation { property: animated_property, @@ -112,28 +169,64 @@ impl PropertyAnimation { (time * (steps as f64)).floor() / (steps as f64) } }; - match self.property { - AnimatedProperty::Top(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().top = value - } - } - AnimatedProperty::Right(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().right = value - } - } - AnimatedProperty::Bottom(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().bottom = value - } - } - AnimatedProperty::Left(ref start, ref end) => { - if let Some(value) = start.interpolate(end, progress) { - style.mutate_positionoffsets().left = value + + macro_rules! match_property( + ( $( [$name:ident; $structname:ident; $field:ident] ),* ) => { + match self.property { + $( + AnimatedProperty::$name(ref start, ref end) => { + if let Some(value) = start.interpolate(end, progress) { + style.$structname().$field = value + } + } + )* } - } - } + }); + match_property!( + [BackgroundColor; mutate_background; background_color], + [BackgroundPosition; mutate_background; background_position], + [BorderBottomColor; mutate_border; border_bottom_color], + [BorderBottomWidth; mutate_border; border_bottom_width], + [BorderLeftColor; mutate_border; border_left_color], + [BorderLeftWidth; mutate_border; border_left_width], + [BorderRightColor; mutate_border; border_right_color], + [BorderRightWidth; mutate_border; border_right_width], + [BorderSpacing; mutate_inheritedtable; border_spacing], + [BorderTopColor; mutate_border; border_top_color], + [BorderTopWidth; mutate_border; border_top_width], + [Bottom; mutate_positionoffsets; bottom], + [Color; mutate_color; color], + [Clip; mutate_effects; clip], + [FontSize; mutate_font; font_size], + [FontWeight; mutate_font; font_weight], + [Height; mutate_box; height], + [Left; mutate_positionoffsets; bottom], + [LetterSpacing; mutate_inheritedtext; letter_spacing], + [LineHeight; mutate_inheritedbox; line_height], + [MarginBottom; mutate_margin; margin_bottom], + [MarginLeft; mutate_margin; margin_left], + [MarginRight; mutate_margin; margin_right], + [MarginTop; mutate_margin; margin_top], + [MaxHeight; mutate_box; max_height], + [MaxWidth; mutate_box; max_width], + [MinHeight; mutate_box; min_height], + [MinWidth; mutate_box; min_width], + [Opacity; mutate_effects; opacity], + [OutlineColor; mutate_outline; outline_color], + [OutlineWidth; mutate_outline; outline_width], + [PaddingBottom; mutate_margin; margin_bottom], + [PaddingLeft; mutate_margin; margin_left], + [PaddingRight; mutate_margin; margin_right], + [PaddingTop; mutate_margin; margin_top], + [Right; mutate_positionoffsets; right], + [TextIndent; mutate_inheritedtext; text_indent], + [TextShadow; mutate_effects; text_shadow], + [Top; mutate_positionoffsets; top], + [VerticalAlign; mutate_box; vertical_align], + [Visibility; mutate_inheritedbox; visibility], + [Width; mutate_box; width], + [WordSpacing; mutate_inheritedtext; word_spacing], + [ZIndex; mutate_box; z_index]); } #[inline] @@ -142,12 +235,52 @@ impl PropertyAnimation { } } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] enum AnimatedProperty { - Top(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), - Right(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + BackgroundColor(Color, Color), + BackgroundPosition(BackgroundPosition, BackgroundPosition), + BorderBottomColor(Color, Color), + BorderBottomWidth(Length, Length), + BorderLeftColor(Color, Color), + BorderLeftWidth(Length, Length), + BorderRightColor(Color, Color), + BorderRightWidth(Length, Length), + BorderSpacing(BorderSpacing, BorderSpacing), + BorderTopColor(Color, Color), + BorderTopWidth(Length, Length), Bottom(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + Color(RGBA, RGBA), + Clip(Option<ClipRect>, Option<ClipRect>), + FontSize(Length, Length), + FontWeight(FontWeight, FontWeight), + Height(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), Left(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + LetterSpacing(Option<Au>, Option<Au>), + LineHeight(LineHeight, LineHeight), + MarginBottom(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MarginLeft(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MarginRight(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MarginTop(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + MaxHeight(LengthOrPercentageOrNone, LengthOrPercentageOrNone), + MaxWidth(LengthOrPercentageOrNone, LengthOrPercentageOrNone), + MinHeight(LengthOrPercentage, LengthOrPercentage), + MinWidth(LengthOrPercentage, LengthOrPercentage), + Opacity(CSSFloat, CSSFloat), + OutlineColor(Color, Color), + OutlineWidth(Length, Length), + PaddingBottom(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + PaddingLeft(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + PaddingRight(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + PaddingTop(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + Right(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + TextIndent(LengthOrPercentage, LengthOrPercentage), + TextShadow(TextShadowList, TextShadowList), + Top(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + VerticalAlign(VerticalAlign, VerticalAlign), + Visibility(Visibility, Visibility), + Width(LengthOrPercentageOrAuto, LengthOrPercentageOrAuto), + WordSpacing(Option<Au>, Option<Au>), + ZIndex(ZIndex, ZIndex), } impl AnimatedProperty { @@ -157,7 +290,47 @@ impl AnimatedProperty { AnimatedProperty::Top(ref a, ref b) | AnimatedProperty::Right(ref a, ref b) | AnimatedProperty::Bottom(ref a, ref b) | - AnimatedProperty::Left(ref a, ref b) => a == b, + AnimatedProperty::Left(ref a, ref b) | + AnimatedProperty::MarginTop(ref a, ref b) | + AnimatedProperty::MarginRight(ref a, ref b) | + AnimatedProperty::MarginBottom(ref a, ref b) | + AnimatedProperty::MarginLeft(ref a, ref b) | + AnimatedProperty::PaddingTop(ref a, ref b) | + AnimatedProperty::PaddingRight(ref a, ref b) | + AnimatedProperty::PaddingBottom(ref a, ref b) | + AnimatedProperty::PaddingLeft(ref a, ref b) | + AnimatedProperty::Width(ref a, ref b) | + AnimatedProperty::Height(ref a, ref b) => a == b, + AnimatedProperty::MaxWidth(ref a, ref b) | + AnimatedProperty::MaxHeight(ref a, ref b) => a == b, + AnimatedProperty::MinWidth(ref a, ref b) | + AnimatedProperty::MinHeight(ref a, ref b) | + AnimatedProperty::TextIndent(ref a, ref b) => a == b, + AnimatedProperty::FontSize(ref a, ref b) | + AnimatedProperty::BorderTopWidth(ref a, ref b) | + AnimatedProperty::BorderRightWidth(ref a, ref b) | + AnimatedProperty::BorderBottomWidth(ref a, ref b) | + AnimatedProperty::BorderLeftWidth(ref a, ref b) => a == b, + AnimatedProperty::BorderTopColor(ref a, ref b) | + AnimatedProperty::BorderRightColor(ref a, ref b) | + AnimatedProperty::BorderBottomColor(ref a, ref b) | + AnimatedProperty::BorderLeftColor(ref a, ref b) | + AnimatedProperty::OutlineColor(ref a, ref b) | + AnimatedProperty::BackgroundColor(ref a, ref b) => a == b, + AnimatedProperty::LineHeight(ref a, ref b) => a == b, + AnimatedProperty::LetterSpacing(ref a, ref b) => a == b, + AnimatedProperty::BackgroundPosition(ref a, ref b) => a == b, + AnimatedProperty::BorderSpacing(ref a, ref b) => a == b, + AnimatedProperty::Clip(ref a, ref b) => a == b, + AnimatedProperty::Color(ref a, ref b) => a == b, + AnimatedProperty::FontWeight(ref a, ref b) => a == b, + AnimatedProperty::Opacity(ref a, ref b) => a == b, + AnimatedProperty::OutlineWidth(ref a, ref b) => a == b, + AnimatedProperty::TextShadow(ref a, ref b) => a == b, + AnimatedProperty::VerticalAlign(ref a, ref b) => a == b, + AnimatedProperty::Visibility(ref a, ref b) => a == b, + AnimatedProperty::WordSpacing(ref a, ref b) => a == b, + AnimatedProperty::ZIndex(ref a, ref b) => a == b, } } } @@ -173,6 +346,20 @@ impl Interpolate for Au { } } +impl <T> Interpolate for Option<T> where T:Interpolate { + #[inline] + fn interpolate(&self, other: &Option<T>, time: f64) -> Option<Option<T>> { + match (self, other) { + (&Some(ref this), &Some(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(Some(value)) + }) + } + (_, _) => None + } + } +} + impl Interpolate for f64 { #[inline] fn interpolate(&self, other: &f64, time: f64) -> Option<f64> { @@ -180,6 +367,136 @@ impl Interpolate for f64 { } } +impl Interpolate for f32 { + #[inline] + fn interpolate(&self, other: &f32, time: f64) -> Option<f32> { + Some(*self + (*other - *self) * (time as f32)) + } +} + +impl Interpolate for i32 { + #[inline] + fn interpolate(&self, other: &i32, time: f64) -> Option<i32> { + let a = *self as f64; + let b = *other as f64; + Some((a + (b - a) * time).round() as i32) + } +} + +impl Interpolate for Visibility { + #[inline] + fn interpolate(&self, other: &Visibility, time: f64) + -> Option<Visibility> { + match (*self, *other) { + (Visibility::visible, _) | (_, Visibility::visible) => { + if time >= 0.0 && time <= 1.0 { + Some(Visibility::visible) + } else if time < 0.0 { + Some(*self) + } else { + Some(*other) + } + } + (_, _) => None, + } + } +} + +impl Interpolate for ZIndex { + #[inline] + fn interpolate(&self, other: &ZIndex, time: f64) + -> Option<ZIndex> { + match (*self, *other) { + (ZIndex::Number(ref this), + ZIndex::Number(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(ZIndex::Number(value)) + }) + } + (_, _) => None, + } + } +} + +impl Interpolate for VerticalAlign { + #[inline] + fn interpolate(&self, other: &VerticalAlign, time: f64) + -> Option<VerticalAlign> { + match (*self, *other) { + (VerticalAlign::Length(ref this), + VerticalAlign::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(VerticalAlign::Length(value)) + }) + } + (_, _) => None, + } + } +} + +impl Interpolate for BorderSpacing { + #[inline] + fn interpolate(&self, other: &BorderSpacing, time: f64) + -> Option<BorderSpacing> { + self.horizontal.interpolate(&other.horizontal, time).and_then(|horizontal| { + self.vertical.interpolate(&other.vertical, time).and_then(|vertical| { + Some(BorderSpacing { horizontal: horizontal, vertical: vertical }) + }) + }) + } +} + +impl Interpolate for RGBA { + #[inline] + fn interpolate(&self, other: &RGBA, time: f64) -> Option<RGBA> { + match (self.red.interpolate(&other.red, time), + self.green.interpolate(&other.green, time), + self.blue.interpolate(&other.blue, time), + self.alpha.interpolate(&other.alpha, time)) { + (Some(red), Some(green), Some(blue), Some(alpha)) => { + Some(RGBA { red: red, green: green, blue: blue, alpha: alpha }) + } + (_, _, _, _) => None + } + } +} + +impl Interpolate for Color { + #[inline] + fn interpolate(&self, other: &Color, time: f64) -> Option<Color> { + match (*self, *other) { + (Color::RGBA(ref this), Color::RGBA(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(Color::RGBA(value)) + }) + } + (_, _) => None, + } + } +} + +impl Interpolate for LengthOrPercentage { + #[inline] + fn interpolate(&self, other: &LengthOrPercentage, time: f64) + -> Option<LengthOrPercentage> { + match (*self, *other) { + (LengthOrPercentage::Length(ref this), + LengthOrPercentage::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentage::Length(value)) + }) + } + (LengthOrPercentage::Percentage(ref this), + LengthOrPercentage::Percentage(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentage::Percentage(value)) + }) + } + (_, _) => None, + } + } +} + impl Interpolate for LengthOrPercentageOrAuto { #[inline] fn interpolate(&self, other: &LengthOrPercentageOrAuto, time: f64) @@ -205,6 +522,137 @@ impl Interpolate for LengthOrPercentageOrAuto { } } +impl Interpolate for LengthOrPercentageOrNone { + #[inline] + fn interpolate(&self, other: &LengthOrPercentageOrNone, time: f64) + -> Option<LengthOrPercentageOrNone> { + match (*self, *other) { + (LengthOrPercentageOrNone::Length(ref this), + LengthOrPercentageOrNone::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentageOrNone::Length(value)) + }) + } + (LengthOrPercentageOrNone::Percentage(ref this), + LengthOrPercentageOrNone::Percentage(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LengthOrPercentageOrNone::Percentage(value)) + }) + } + (LengthOrPercentageOrNone::None, LengthOrPercentageOrNone::None) => { + Some(LengthOrPercentageOrNone::None) + } + (_, _) => None, + } + } +} + +impl Interpolate for LineHeight { + #[inline] + fn interpolate(&self, other: &LineHeight, time: f64) + -> Option<LineHeight> { + match (*self, *other) { + (LineHeight::Length(ref this), + LineHeight::Length(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LineHeight::Length(value)) + }) + } + (LineHeight::Number(ref this), + LineHeight::Number(ref other)) => { + this.interpolate(other, time).and_then(|value| { + Some(LineHeight::Number(value)) + }) + } + (LineHeight::Normal, LineHeight::Normal) => { + Some(LineHeight::Normal) + } + (_, _) => None, + } + } +} + +impl Interpolate for FontWeight { + #[inline] + fn interpolate(&self, other: &FontWeight, time: f64) + -> Option<FontWeight> { + let a = (*self as isize) as f64; + let b = (*other as isize) as f64; + let weight: Option<FontWeight> = FromPrimitive::from_isize((a + (b - a) * time).round() as isize); + weight + } +} + +impl Interpolate for ClipRect { + #[inline] + fn interpolate(&self, other: &ClipRect, time: f64) + -> Option<ClipRect> { + match (self.top.interpolate(&other.top, time), + self.right.interpolate(&other.right, time), + self.bottom.interpolate(&other.bottom, time), + self.left.interpolate(&other.left, time)) { + (Some(top), Some(right), Some(bottom), Some(left)) => { + Some(ClipRect { top: top, right: right, bottom: bottom, left: left }) + }, + (_, _, _, _) => None, + } + } +} + +impl Interpolate for BackgroundPosition { + #[inline] + fn interpolate(&self, other: &BackgroundPosition, time: f64) + -> Option<BackgroundPosition> { + match (self.horizontal.interpolate(&other.horizontal, time), + self.vertical.interpolate(&other.vertical, time)) { + (Some(horizontal), Some(vertical)) => { + Some(BackgroundPosition { horizontal: horizontal, vertical: vertical }) + }, + (_, _) => None, + } + } +} + +impl Interpolate for TextShadow { + #[inline] + fn interpolate(&self, other: &TextShadow, time: f64) + -> Option<TextShadow> { + match (self.offset_x.interpolate(&other.offset_x, time), + self.offset_y.interpolate(&other.offset_y, time), + self.blur_radius.interpolate(&other.blur_radius, time), + self.color.interpolate(&other.color, time)) { + (Some(offset_x), Some(offset_y), Some(blur_radius), Some(color)) => { + Some(TextShadow { offset_x: offset_x, offset_y: offset_y, blur_radius: blur_radius, color: color }) + }, + (_, _, _, _) => None, + } + } +} + +impl Interpolate for TextShadowList { + #[inline] + fn interpolate(&self, other: &TextShadowList, time: f64) + -> Option<TextShadowList> { + let zero = TextShadow { + offset_x: Au(0), + offset_y: Au(0), + blur_radius: Au(0), + color: Color::RGBA(RGBA { + red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0 + }) + }; + + let interpolate_each = |(a, b): (&TextShadow, &TextShadow)| { + a.interpolate(b, time).unwrap() + }; + + Some(TextShadowList(match self.0.len().cmp(&other.0.len()) { + Ordering::Less => other.0.iter().chain(repeat(&zero)).zip(other.0.iter()).map(interpolate_each).collect(), + _ => self.0.iter().zip(other.0.iter().chain(repeat(&zero))).map(interpolate_each).collect(), + })) + } +} + /// Accesses an element of an array, "wrapping around" using modular arithmetic. This is needed /// to handle values of differing lengths according to CSS-TRANSITIONS § 2. pub trait GetMod { diff --git a/components/style/legacy.rs b/components/style/legacy.rs index 414ed650550..7ddee2f8a0d 100644 --- a/components/style/legacy.rs +++ b/components/style/legacy.rs @@ -194,7 +194,7 @@ impl PresentationalHintSynthesis for Stylist { // the math for <textarea> is a little different since we need to take // scrollbar size into consideration (but we don't have a scrollbar yet!) // - // https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-width + // https://html.spec.whatwg.org/multipage/#textarea-effective-width let value = specified::Length::ServoCharacterWidth(specified::CharacterWidth(value)); matching_rules_list.vec_push(from_declaration( PropertyDeclaration::Width(SpecifiedValue( @@ -207,7 +207,7 @@ impl PresentationalHintSynthesis for Stylist { Some(value) if value != 0 => { // TODO(mttr) This should take scrollbar size into consideration. // - // https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-height + // https://html.spec.whatwg.org/multipage/#textarea-effective-height let value = specified::Length::FontRelative(specified::FontRelativeLength::Em(value as CSSFloat)); matching_rules_list.vec_push(from_declaration( PropertyDeclaration::Height(SpecifiedValue( diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs index ce69b0b0716..2f649e1dda1 100644 --- a/components/style/media_queries.rs +++ b/components/style/media_queries.rs @@ -29,7 +29,7 @@ impl Range<specified::Length> { match width { &specified::Length::Absolute(value) => value, &specified::Length::FontRelative(value) => { - // http://dev.w3.org/csswg/mediaqueries3/ - Section 6 + // http://dev.w3.org/csswg/mediaqueries3/#units // em units are relative to the initial font-size. let initial_font_size = longhands::font_size::get_initial_value(); value.to_computed_value(initial_font_size, initial_font_size) @@ -58,11 +58,14 @@ impl<T: Ord> Range<T> { } } +/// http://dev.w3.org/csswg/mediaqueries-3/#media1 #[derive(PartialEq, Copy, Debug)] pub enum Expression { + /// http://dev.w3.org/csswg/mediaqueries-3/#width Width(Range<specified::Length>), } +/// http://dev.w3.org/csswg/mediaqueries-3/#media0 #[derive(PartialEq, Eq, Copy, Debug)] pub enum Qualifier { Only, @@ -87,6 +90,7 @@ impl MediaQuery { } } +/// http://dev.w3.org/csswg/mediaqueries-3/#media0 #[derive(PartialEq, Eq, Copy, Debug)] pub enum MediaQueryType { All, // Always true diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 234fecfc9eb..51234eece8b 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -385,7 +385,7 @@ pub mod longhands { use cssparser::ToCss; use text_writer::{self, TextWriter}; - #[derive(PartialEq, Clone, Eq, Copy)] + #[derive(PartialEq, Clone, Eq, Copy, Debug)] pub enum T { Auto, Number(i32), @@ -1195,7 +1195,7 @@ pub mod longhands { pub mod computed_value { use values::computed::LengthOrPercentage; - #[derive(PartialEq, Copy, Clone)] + #[derive(PartialEq, Copy, Clone, Debug)] pub struct T { pub horizontal: LengthOrPercentage, pub vertical: LengthOrPercentage, @@ -1597,7 +1597,7 @@ pub mod longhands { } pub mod computed_value { use std::fmt; - #[derive(PartialEq, Eq, Copy, Clone, Hash)] + #[derive(PartialEq, Eq, Copy, Clone, Hash, FromPrimitive)] pub enum T { % for weight in range(100, 901, 100): Weight${weight} = ${weight}, @@ -2695,22 +2695,38 @@ pub mod longhands { </%self:longhand> <%self:longhand name="filter"> - use values::specified::Angle; - pub use self::computed_value::T as SpecifiedValue; - pub use self::computed_value::Filter; - use values::computed::ComputedValueAsSpecified; + //pub use self::computed_value::T as SpecifiedValue; + use values::computed::{Context, ToComputedValue}; + use values::specified::{Angle, Length}; + use values::CSSFloat; + use cssparser::ToCss; + use text_writer::{self, TextWriter}; - impl ComputedValueAsSpecified for SpecifiedValue {} + #[derive(Clone, PartialEq)] + pub struct SpecifiedValue(Vec<SpecifiedFilter>); + + // TODO(pcwalton): `drop-shadow` + #[derive(Clone, PartialEq, Debug)] + pub enum SpecifiedFilter { + Blur(Length), + Brightness(CSSFloat), + Contrast(CSSFloat), + Grayscale(CSSFloat), + HueRotate(Angle), + Invert(CSSFloat), + Opacity(CSSFloat), + Saturate(CSSFloat), + Sepia(CSSFloat), + } pub mod computed_value { - use values::specified::Angle; + use util::geometry::Au; use values::CSSFloat; - use cssparser::ToCss; - use text_writer::{self, TextWriter}; + use values::specified::{Angle}; - // TODO(pcwalton): `blur`, `drop-shadow` #[derive(Clone, PartialEq, Debug)] pub enum Filter { + Blur(Au), Brightness(CSSFloat), Contrast(CSSFloat), Grayscale(CSSFloat), @@ -2721,54 +2737,16 @@ pub mod longhands { Sepia(CSSFloat), } - impl ToCss for Filter { - fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { - match *self { - Filter::Brightness(value) => try!(write!(dest, "brightness({})", value)), - Filter::Contrast(value) => try!(write!(dest, "contrast({})", value)), - Filter::Grayscale(value) => try!(write!(dest, "grayscale({})", value)), - Filter::HueRotate(value) => { - try!(dest.write_str("hue-rotate(")); - try!(value.to_css(dest)); - try!(dest.write_str(")")); - } - Filter::Invert(value) => try!(write!(dest, "invert({})", value)), - Filter::Opacity(value) => try!(write!(dest, "opacity({})", value)), - Filter::Saturate(value) => try!(write!(dest, "saturate({})", value)), - Filter::Sepia(value) => try!(write!(dest, "sepia({})", value)), - } - Ok(()) - } - } - #[derive(Clone, PartialEq, Debug)] - pub struct T { - pub filters: Vec<Filter>, - } - - impl ToCss for T { - fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { - let mut iter = self.filters.iter(); - if let Some(filter) = iter.next() { - try!(filter.to_css(dest)); - } else { - try!(dest.write_str("none")); - return Ok(()) - } - for filter in iter { - try!(dest.write_str(" ")); - try!(filter.to_css(dest)); - } - Ok(()) - } - } + pub struct T { pub filters: Vec<Filter> } impl T { /// Creates a new filter pipeline. #[inline] pub fn new(filters: Vec<Filter>) -> T { - T { - filters: filters, + T + { + filters: filters, } } @@ -2788,6 +2766,7 @@ pub mod longhands { #[inline] pub fn opacity(&self) -> CSSFloat { let mut opacity = 1.0; + for filter in self.filters.iter() { if let Filter::Opacity(ref opacity_value) = *filter { opacity *= *opacity_value @@ -2798,6 +2777,48 @@ pub mod longhands { } } + impl ToCss for SpecifiedValue { + fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { + let mut iter = self.0.iter(); + if let Some(filter) = iter.next() { + try!(filter.to_css(dest)); + } else { + try!(dest.write_str("none")); + return Ok(()) + } + for filter in iter { + try!(dest.write_str(" ")); + try!(filter.to_css(dest)); + } + Ok(()) + } + } + + impl ToCss for SpecifiedFilter { + fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { + match *self { + SpecifiedFilter::Blur(value) => { + try!(dest.write_str("blur(")); + try!(value.to_css(dest)); + try!(dest.write_str(")")); + } + SpecifiedFilter::Brightness(value) => try!(write!(dest, "brightness({})", value)), + SpecifiedFilter::Contrast(value) => try!(write!(dest, "contrast({})", value)), + SpecifiedFilter::Grayscale(value) => try!(write!(dest, "grayscale({})", value)), + SpecifiedFilter::HueRotate(value) => { + try!(dest.write_str("hue-rotate(")); + try!(value.to_css(dest)); + try!(dest.write_str(")")); + } + SpecifiedFilter::Invert(value) => try!(write!(dest, "invert({})", value)), + SpecifiedFilter::Opacity(value) => try!(write!(dest, "opacity({})", value)), + SpecifiedFilter::Saturate(value) => try!(write!(dest, "saturate({})", value)), + SpecifiedFilter::Sepia(value) => try!(write!(dest, "sepia({})", value)), + } + Ok(()) + } + } + #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T::new(Vec::new()) @@ -2806,27 +2827,28 @@ pub mod longhands { pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { let mut filters = Vec::new(); if input.try(|input| input.expect_ident_matching("none")).is_ok() { - return Ok(SpecifiedValue::new(filters)) + return Ok(SpecifiedValue(filters)) } loop { if let Ok(function_name) = input.try(|input| input.expect_function()) { filters.push(try!(input.parse_nested_block(|input| { match_ignore_ascii_case! { function_name, - "brightness" => parse_factor(input).map(Filter::Brightness), - "contrast" => parse_factor(input).map(Filter::Contrast), - "grayscale" => parse_factor(input).map(Filter::Grayscale), - "hue-rotate" => Angle::parse(input).map(Filter::HueRotate), - "invert" => parse_factor(input).map(Filter::Invert), - "opacity" => parse_factor(input).map(Filter::Opacity), - "saturate" => parse_factor(input).map(Filter::Saturate), - "sepia" => parse_factor(input).map(Filter::Sepia) + "blur" => specified::Length::parse_non_negative(input).map(SpecifiedFilter::Blur), + "brightness" => parse_factor(input).map(SpecifiedFilter::Brightness), + "contrast" => parse_factor(input).map(SpecifiedFilter::Contrast), + "grayscale" => parse_factor(input).map(SpecifiedFilter::Grayscale), + "hue-rotate" => Angle::parse(input).map(SpecifiedFilter::HueRotate), + "invert" => parse_factor(input).map(SpecifiedFilter::Invert), + "opacity" => parse_factor(input).map(SpecifiedFilter::Opacity), + "saturate" => parse_factor(input).map(SpecifiedFilter::Saturate), + "sepia" => parse_factor(input).map(SpecifiedFilter::Sepia) _ => Err(()) } }))); } else if filters.is_empty() { return Err(()) } else { - return Ok(SpecifiedValue::new(filters)) + return Ok(SpecifiedValue(filters)) } } } @@ -2839,6 +2861,26 @@ pub mod longhands { _ => Err(()) } } + + impl ToComputedValue for SpecifiedValue { + type ComputedValue = computed_value::T; + + fn to_computed_value(&self, context: &computed::Context) -> computed_value::T { + computed_value::T{ filters: self.0.iter().map(|value| { + match value { + &SpecifiedFilter::Blur(factor) => computed_value::Filter::Blur(factor.to_computed_value(context)), + &SpecifiedFilter::Brightness(factor) => computed_value::Filter::Brightness(factor), + &SpecifiedFilter::Contrast(factor) => computed_value::Filter::Contrast(factor), + &SpecifiedFilter::Grayscale(factor) => computed_value::Filter::Grayscale(factor), + &SpecifiedFilter::HueRotate(factor) => computed_value::Filter::HueRotate(factor), + &SpecifiedFilter::Invert(factor) => computed_value::Filter::Invert(factor), + &SpecifiedFilter::Opacity(factor) => computed_value::Filter::Opacity(factor), + &SpecifiedFilter::Saturate(factor) => computed_value::Filter::Saturate(factor), + &SpecifiedFilter::Sepia(factor) => computed_value::Filter::Sepia(factor), + } + }).collect() } + } + } </%self:longhand> <%self:longhand name="transform"> @@ -3663,27 +3705,147 @@ pub mod longhands { #[derive(Copy, Clone, Debug, PartialEq)] pub enum TransitionProperty { All, - Top, - Right, + BackgroundColor, + BackgroundPosition, + BorderBottomColor, + BorderBottomWidth, + BorderLeftColor, + BorderLeftWidth, + BorderRightColor, + BorderRightWidth, + BorderSpacing, + BorderTopColor, + BorderTopWidth, Bottom, + Color, + Clip, + FontSize, + FontWeight, + Height, Left, - } - - pub static ALL_TRANSITION_PROPERTIES: [TransitionProperty; 4] = [ - TransitionProperty::Top, - TransitionProperty::Right, + LetterSpacing, + LineHeight, + MarginBottom, + MarginLeft, + MarginRight, + MarginTop, + MaxHeight, + MaxWidth, + MinHeight, + MinWidth, + Opacity, + OutlineColor, + OutlineWidth, + PaddingBottom, + PaddingLeft, + PaddingRight, + PaddingTop, + Right, + TextIndent, + TextShadow, + Top, + VerticalAlign, + Visibility, + Width, + WordSpacing, + ZIndex, + } + + pub static ALL_TRANSITION_PROPERTIES: [TransitionProperty; 44] = [ + TransitionProperty::BackgroundColor, + TransitionProperty::BackgroundPosition, + TransitionProperty::BorderBottomColor, + TransitionProperty::BorderBottomWidth, + TransitionProperty::BorderLeftColor, + TransitionProperty::BorderLeftWidth, + TransitionProperty::BorderRightColor, + TransitionProperty::BorderRightWidth, + TransitionProperty::BorderSpacing, + TransitionProperty::BorderTopColor, + TransitionProperty::BorderTopWidth, TransitionProperty::Bottom, + TransitionProperty::Color, + TransitionProperty::Clip, + TransitionProperty::FontSize, + TransitionProperty::FontWeight, + TransitionProperty::Height, TransitionProperty::Left, + TransitionProperty::LetterSpacing, + TransitionProperty::LineHeight, + TransitionProperty::MarginBottom, + TransitionProperty::MarginLeft, + TransitionProperty::MarginRight, + TransitionProperty::MarginTop, + TransitionProperty::MaxHeight, + TransitionProperty::MaxWidth, + TransitionProperty::MinHeight, + TransitionProperty::MinWidth, + TransitionProperty::Opacity, + TransitionProperty::OutlineColor, + TransitionProperty::OutlineWidth, + TransitionProperty::PaddingBottom, + TransitionProperty::PaddingLeft, + TransitionProperty::PaddingRight, + TransitionProperty::PaddingTop, + TransitionProperty::Right, + TransitionProperty::TextIndent, + TransitionProperty::TextShadow, + TransitionProperty::Top, + TransitionProperty::VerticalAlign, + TransitionProperty::Visibility, + TransitionProperty::Width, + TransitionProperty::WordSpacing, + TransitionProperty::ZIndex, ]; impl ToCss for TransitionProperty { fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { match *self { TransitionProperty::All => dest.write_str("all"), - TransitionProperty::Top => dest.write_str("top"), - TransitionProperty::Right => dest.write_str("right"), + TransitionProperty::BackgroundColor => dest.write_str("background-color"), + TransitionProperty::BackgroundPosition => dest.write_str("background-position"), + TransitionProperty::BorderBottomColor => dest.write_str("border-bottom-color"), + TransitionProperty::BorderBottomWidth => dest.write_str("border-bottom-width"), + TransitionProperty::BorderLeftColor => dest.write_str("border-left-color"), + TransitionProperty::BorderLeftWidth => dest.write_str("border-left-width"), + TransitionProperty::BorderRightColor => dest.write_str("border-right-color"), + TransitionProperty::BorderRightWidth => dest.write_str("border-right-width"), + TransitionProperty::BorderSpacing => dest.write_str("border-spacing"), + TransitionProperty::BorderTopColor => dest.write_str("border-top-color"), + TransitionProperty::BorderTopWidth => dest.write_str("border-top-width"), TransitionProperty::Bottom => dest.write_str("bottom"), + TransitionProperty::Color => dest.write_str("color"), + TransitionProperty::Clip => dest.write_str("clip"), + TransitionProperty::FontSize => dest.write_str("font-size"), + TransitionProperty::FontWeight => dest.write_str("font-weight"), + TransitionProperty::Height => dest.write_str("height"), TransitionProperty::Left => dest.write_str("left"), + TransitionProperty::LetterSpacing => dest.write_str("letter-spacing"), + TransitionProperty::LineHeight => dest.write_str("line-height"), + TransitionProperty::MarginBottom => dest.write_str("margin-bottom"), + TransitionProperty::MarginLeft => dest.write_str("margin-left"), + TransitionProperty::MarginRight => dest.write_str("margin-right"), + TransitionProperty::MarginTop => dest.write_str("margin-top"), + TransitionProperty::MaxHeight => dest.write_str("max-height"), + TransitionProperty::MaxWidth => dest.write_str("max-width"), + TransitionProperty::MinHeight => dest.write_str("min-height"), + TransitionProperty::MinWidth => dest.write_str("min-width"), + TransitionProperty::Opacity => dest.write_str("opacity"), + TransitionProperty::OutlineColor => dest.write_str("outline-color"), + TransitionProperty::OutlineWidth => dest.write_str("outline-width"), + TransitionProperty::PaddingBottom => dest.write_str("padding-bottom"), + TransitionProperty::PaddingLeft => dest.write_str("padding-left"), + TransitionProperty::PaddingRight => dest.write_str("padding-right"), + TransitionProperty::PaddingTop => dest.write_str("padding-top"), + TransitionProperty::Right => dest.write_str("right"), + TransitionProperty::TextIndent => dest.write_str("text-indent"), + TransitionProperty::TextShadow => dest.write_str("text-shadow"), + TransitionProperty::Top => dest.write_str("top"), + TransitionProperty::VerticalAlign => dest.write_str("vertical-align"), + TransitionProperty::Visibility => dest.write_str("visibility"), + TransitionProperty::Width => dest.write_str("width"), + TransitionProperty::WordSpacing => dest.write_str("word-spacing"), + TransitionProperty::ZIndex => dest.write_str("z-index"), } } } @@ -3716,10 +3878,50 @@ pub mod longhands { match_ignore_ascii_case! { try!(input.expect_ident()), "all" => Ok(TransitionProperty::All), - "top" => Ok(TransitionProperty::Top), - "right" => Ok(TransitionProperty::Right), + "background-color" => Ok(TransitionProperty::BackgroundColor), + "background-position" => Ok(TransitionProperty::BackgroundPosition), + "border-bottom-color" => Ok(TransitionProperty::BorderBottomColor), + "border-bottom-width" => Ok(TransitionProperty::BorderBottomWidth), + "border-left-color" => Ok(TransitionProperty::BorderLeftColor), + "border-left-width" => Ok(TransitionProperty::BorderLeftWidth), + "border-right-color" => Ok(TransitionProperty::BorderRightColor), + "border-right-width" => Ok(TransitionProperty::BorderRightWidth), + "border-spacing" => Ok(TransitionProperty::BorderSpacing), + "border-top-color" => Ok(TransitionProperty::BorderTopColor), + "border-top-width" => Ok(TransitionProperty::BorderTopWidth), "bottom" => Ok(TransitionProperty::Bottom), - "left" => Ok(TransitionProperty::Left) + "color" => Ok(TransitionProperty::Color), + "clip" => Ok(TransitionProperty::Clip), + "font-size" => Ok(TransitionProperty::FontSize), + "font-weight" => Ok(TransitionProperty::FontWeight), + "height" => Ok(TransitionProperty::Height), + "left" => Ok(TransitionProperty::Left), + "letter-spacing" => Ok(TransitionProperty::LetterSpacing), + "line-height" => Ok(TransitionProperty::LineHeight), + "margin-bottom" => Ok(TransitionProperty::MarginBottom), + "margin-left" => Ok(TransitionProperty::MarginLeft), + "margin-right" => Ok(TransitionProperty::MarginRight), + "margin-top" => Ok(TransitionProperty::MarginTop), + "max-height" => Ok(TransitionProperty::MaxHeight), + "max-width" => Ok(TransitionProperty::MaxWidth), + "min-height" => Ok(TransitionProperty::MinHeight), + "min-width" => Ok(TransitionProperty::MinWidth), + "opacity" => Ok(TransitionProperty::Opacity), + "outline-color" => Ok(TransitionProperty::OutlineColor), + "outline-width" => Ok(TransitionProperty::OutlineWidth), + "padding-bottom" => Ok(TransitionProperty::PaddingBottom), + "padding-left" => Ok(TransitionProperty::PaddingLeft), + "padding-right" => Ok(TransitionProperty::PaddingRight), + "padding-top" => Ok(TransitionProperty::PaddingTop), + "right" => Ok(TransitionProperty::Right), + "text-indent" => Ok(TransitionProperty::TextIndent), + "text-shadow" => Ok(TransitionProperty::TextShadow), + "top" => Ok(TransitionProperty::Top), + "vertical-align" => Ok(TransitionProperty::VerticalAlign), + "visibility" => Ok(TransitionProperty::Visibility), + "width" => Ok(TransitionProperty::Width), + "word-spacing" => Ok(TransitionProperty::WordSpacing), + "z-index" => Ok(TransitionProperty::ZIndex) _ => Err(()) } } diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 50cc34ed9fa..b47ef8954e9 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -21,10 +21,18 @@ use font_face::{FontFaceRule, parse_font_face_block}; use util::smallvec::{SmallVec, SmallVec2}; +/// Each style rule has an origin, which determines where it enters the cascade. +/// +/// http://dev.w3.org/csswg/css-cascade/#cascading-origins #[derive(Clone, PartialEq, Eq, Copy, Debug)] pub enum Origin { + /// http://dev.w3.org/csswg/css-cascade/#cascade-origin-ua UserAgent, + + /// http://dev.w3.org/csswg/css-cascade/#cascade-origin-author Author, + + /// http://dev.w3.org/csswg/css-cascade/#cascade-origin-user User, } diff --git a/components/util/opts.rs b/components/util/opts.rs index 9d184feb555..388ee9ce70a 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -121,9 +121,12 @@ pub struct Opts { /// Dumps the flow tree after a layout. pub dump_flow_tree: bool, - /// Dumps the flow tree after a layout. + /// Dumps the display list after a layout. pub dump_display_list: bool, + /// Dumps the display list after optimization (post layout, at painting time). + pub dump_display_list_optimized: bool, + /// Emits notifications when there is a relayout. pub relayout_event: bool, @@ -156,6 +159,7 @@ pub fn print_debug_usage(app: &str) { print_option("disable-text-aa", "Disable antialiasing of rendered text."); print_option("dump-flow-tree", "Print the flow tree after each layout."); print_option("dump-display-list", "Print the display list after each layout."); + print_option("dump-display-list-optimized", "Print optimized display list (at paint time)."); print_option("relayout-event", "Print notifications when there is a relayout."); print_option("profile-tasks", "Instrument each task, writing the output to a file."); print_option("show-compositor-borders", "Paint borders along layer and tile boundaries."); @@ -216,6 +220,7 @@ pub fn default_opts() -> Opts { user_agent: None, dump_flow_tree: false, dump_display_list: false, + dump_display_list_optimized: false, relayout_event: false, validate_display_list_geometry: false, profile_tasks: false, @@ -379,6 +384,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool { enable_text_antialiasing: !debug_options.contains(&"disable-text-aa"), dump_flow_tree: debug_options.contains(&"dump-flow-tree"), dump_display_list: debug_options.contains(&"dump-display-list"), + dump_display_list_optimized: debug_options.contains(&"dump-display-list-optimized"), relayout_event: debug_options.contains(&"relayout-event"), validate_display_list_geometry: debug_options.contains(&"validate-display-list-geometry"), resources_path: opt_match.opt_str("resources-path"), diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml index ec68305b885..337f8a6498a 100644 --- a/components/webdriver_server/Cargo.toml +++ b/components/webdriver_server/Cargo.toml @@ -7,5 +7,16 @@ authors = ["The Servo Project Developers"] name = "webdriver_server" path = "lib.rs" +[dependencies.msg] +path = "../msg" + +[dependencies.util] +path = "../util" + [dependencies.webdriver] -git = "https://github.com/jgraham/webdriver-rust.git"
\ No newline at end of file +git = "https://github.com/jgraham/webdriver-rust.git" + +[dependencies] +rustc-serialize="0.3.4" +url = "0.2.16" +uuid = "0.1.11"
\ No newline at end of file diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index 5377106654a..e8a1f4771b8 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -6,27 +6,125 @@ #![crate_type = "rlib"] #![feature(net)] +#![feature(rustc_private)] + +#[macro_use] +extern crate log; extern crate webdriver; +extern crate msg; +extern crate url; +extern crate util; +extern crate "rustc-serialize" as rustc_serialize; +extern crate uuid; + +use msg::constellation_msg::{ConstellationChan, LoadData}; +use msg::constellation_msg::Msg as ConstellationMsg; +use std::sync::mpsc::channel; -use webdriver::command::WebDriverMessage; -use webdriver::error::WebDriverResult; -use webdriver::response::WebDriverResponse; +use url::Url; +use webdriver::command::{WebDriverMessage, WebDriverCommand}; +use webdriver::command::GetParameters; +use webdriver::response::{ + WebDriverResponse, NewSessionResponse, ValueResponse}; use webdriver::server::{self, WebDriverHandler, Session}; +use webdriver::error::{WebDriverResult, WebDriverError, ErrorStatus}; +use util::task::spawn_named; +use uuid::Uuid; +use std::borrow::ToOwned; use std::net::IpAddr; +use rustc_serialize::json::{Json, ToJson}; +use std::collections::BTreeMap; + +pub fn start_server(port: u16, constellation_chan: ConstellationChan) { + let handler = Handler::new(constellation_chan); -pub fn start_server(port: u16) { - server::start(IpAddr::new_v4(0, 0, 0, 0), port, Handler); + spawn_named("WebdriverHttpServer".to_owned(), move || { + server::start(IpAddr::new_v4(0, 0, 0, 0), port, handler); + }); } -struct Handler; +struct WebdriverSession { + id: Uuid +} -impl WebDriverHandler for Handler { - fn handle_command(&mut self, _session: &Option<Session>, _msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse> { +struct Handler { + session: Option<WebdriverSession>, + constellation_chan: ConstellationChan +} + +impl WebdriverSession { + pub fn new() -> WebdriverSession { + WebdriverSession { + id: Uuid::new_v4() + } + } +} + +impl Handler { + pub fn new(constellation_chan: ConstellationChan) -> Handler { + Handler { + session: None, + constellation_chan: constellation_chan + } + } + + fn handle_new_session(&mut self) -> WebDriverResult<WebDriverResponse> { + if self.session.is_none() { + let session = WebdriverSession::new(); + let rv = Ok(WebDriverResponse::NewSession( + NewSessionResponse::new( + session.id.to_string(), + Json::Object(BTreeMap::new())))); + self.session = Some(session); + rv + } else { + Err(WebDriverError::new(ErrorStatus::UnknownError, + "Session already created")) + } + } + + fn handle_get(&self, parameters: &GetParameters) -> WebDriverResult<WebDriverResponse> { + let url = match Url::parse(¶meters.url[..]) { + Ok(url) => url, + Err(_) => return Err(WebDriverError::new(ErrorStatus::InvalidArgument, + "Invalid URL")) + }; + + let (sender, reciever) = channel(); + let ConstellationChan(ref const_chan) = self.constellation_chan; + const_chan.send(ConstellationMsg::GetRootPipeline(sender)).unwrap(); + + let pipeline_id = reciever.recv().unwrap().unwrap(); + + let load_data = LoadData::new(url); + const_chan.send(ConstellationMsg::LoadUrl(pipeline_id, load_data)).unwrap(); + //TODO: Now we ought to wait until we get a load event Ok(WebDriverResponse::Void) } + fn handle_get_window_handle(&self) -> WebDriverResult<WebDriverResponse> { + // For now we assume there's only one window so just use the session + // id as the window id + let handle = self.session.as_ref().unwrap().id.to_string(); + Ok(WebDriverResponse::Generic(ValueResponse::new(handle.to_json()))) + } +} + +impl WebDriverHandler for Handler { + fn handle_command(&mut self, _session: &Option<Session>, msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse> { + + match msg.command { + WebDriverCommand::NewSession => self.handle_new_session(), + WebDriverCommand::Get(ref parameters) => self.handle_get(parameters), + WebDriverCommand::GetWindowHandle => self.handle_get_window_handle(), + _ => Err(WebDriverError::new(ErrorStatus::UnsupportedOperation, + "Command not implemented")) + } + } + fn delete_session(&mut self, _session: &Option<Session>) { + self.session = None; } } diff --git a/etc/layout_viewer/README b/etc/layout_viewer/README index ee0b065a87b..11c765e0a74 100644 --- a/etc/layout_viewer/README +++ b/etc/layout_viewer/README @@ -1,6 +1,6 @@ To generate a layout trace: -./servo --trace-layout url +./mach run -Z trace-layout <url> A layout_trace.json file will be writtent to the current directory that can be loaded by the viewer. diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 60ad7527f97..2e6a5fbe6ec 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -37,7 +37,7 @@ source = "git+https://github.com/tomaka/android-rs-glue#5a68056599fb498b0cf3715f [[package]] name = "azure" version = "0.1.0" -source = "git+https://github.com/servo/rust-azure#358fc5da081cf7d0618fae2d9d5582951beb791f" +source = "git+https://github.com/servo/rust-azure#3e5daf667a62f702dc16285e923464458bef785f" dependencies = [ "core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)", "core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)", @@ -63,6 +63,9 @@ dependencies = [ "cssparser 0.2.0 (git+https://github.com/servo/rust-cssparser)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)", "gfx 0.0.1", + "gleam 0.0.1 (git+https://github.com/servo/gleam)", + "glutin 0.0.7 (git+https://github.com/servo/glutin?branch=servo)", + "msg 0.0.1", "util 0.0.1", ] @@ -111,6 +114,7 @@ dependencies = [ "time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "webdriver_server 0.0.1", ] [[package]] @@ -365,7 +369,7 @@ dependencies = [ [[package]] name = "gleam" version = "0.0.1" -source = "git+https://github.com/servo/gleam#fb17a364f314a35a6d209e875b5e90a920d41e86" +source = "git+https://github.com/servo/gleam#70c5f2ea3ef3602277b7c380c24b504e42338056" dependencies = [ "gl_common 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -854,6 +858,7 @@ dependencies = [ "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "compositing 0.0.1", "devtools 0.0.1", + "devtools_traits 0.0.1", "gfx 0.0.1", "glutin_app 0.0.1", "layout 0.0.1", @@ -1007,7 +1012,7 @@ dependencies = [ [[package]] name = "webdriver" version = "0.0.1" -source = "git+https://github.com/jgraham/webdriver-rust.git#906806d51783b5caad89432bf8ce008f2f4968fc" +source = "git+https://github.com/jgraham/webdriver-rust.git#4f543416a269b9d0d7ee5332db489768c2a769dd" dependencies = [ "hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1020,6 +1025,11 @@ dependencies = [ name = "webdriver_server" version = "0.0.1" dependencies = [ + "msg 0.0.1", + "rustc-serialize 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "util 0.0.1", + "uuid 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "webdriver 0.0.1 (git+https://github.com/jgraham/webdriver-rust.git)", ] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 9abf50ea0b3..6d3715bbd7e 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -24,9 +24,14 @@ dependencies = [ ] [[package]] +name = "android_glue" +version = "0.0.1" +source = "git+https://github.com/tomaka/android-rs-glue#5a68056599fb498b0cf3715fd359894825e3b856" + +[[package]] name = "azure" version = "0.1.0" -source = "git+https://github.com/servo/rust-azure#358fc5da081cf7d0618fae2d9d5582951beb791f" +source = "git+https://github.com/servo/rust-azure#3e5daf667a62f702dc16285e923464458bef785f" dependencies = [ "core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)", "core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)", @@ -52,6 +57,9 @@ dependencies = [ "cssparser 0.2.0 (git+https://github.com/servo/rust-cssparser)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)", "gfx 0.0.1", + "gleam 0.0.1 (git+https://github.com/servo/gleam)", + "glutin 0.0.7 (git+https://github.com/servo/glutin?branch=servo)", + "msg 0.0.1", "util 0.0.1", ] @@ -69,6 +77,16 @@ version = "0.0.4" source = "git+https://github.com/tomaka/clock_ticks#6a3005279bedc406b13eea09ff92447f05ca0de6" [[package]] +name = "cocoa" +version = "0.1.1" +source = "git+https://github.com/servo/rust-cocoa#26d02e3f3606223645dde173a7bb924bce4836de" +dependencies = [ + "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "compositing" version = "0.0.1" dependencies = [ @@ -91,6 +109,7 @@ dependencies = [ "time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", + "webdriver_server 0.0.1", ] [[package]] @@ -278,6 +297,14 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "gdi32-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "geom" version = "0.1.0" source = "git+https://github.com/servo/rust-geom#c47fc0f927b6d6e5543fe3b5445c86810831dce1" @@ -337,7 +364,7 @@ dependencies = [ [[package]] name = "gleam" version = "0.0.1" -source = "git+https://github.com/servo/gleam#fb17a364f314a35a6d209e875b5e90a920d41e86" +source = "git+https://github.com/servo/gleam#70c5f2ea3ef3602277b7c380c24b504e42338056" dependencies = [ "gl_common 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,6 +373,25 @@ dependencies = [ ] [[package]] +name = "glutin" +version = "0.0.7" +source = "git+https://github.com/servo/glutin?branch=servo#0feab4842c5b229bfe88739d2c526d03c198fd33" +dependencies = [ + "android_glue 0.0.1 (git+https://github.com/tomaka/android-rs-glue)", + "cocoa 0.1.1 (git+https://github.com/servo/rust-cocoa)", + "core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)", + "core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)", + "gdi32-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_common 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_generator 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "khronos_api 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "user32-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "glx" version = "0.0.1" source = "git+https://github.com/servo/rust-glx#f2103861d38076ef5e01a8c2f58df1e79ca12f41" @@ -423,6 +469,14 @@ dependencies = [ ] [[package]] +name = "kernel32-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "khronos_api" version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -517,6 +571,14 @@ version = "0.0.2" source = "git+https://github.com/reem/rust-mac#6316d3f4663756180fd236b126a84e245e978765" [[package]] +name = "malloc_buf" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "matches" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -598,6 +660,15 @@ dependencies = [ ] [[package]] +name = "objc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "malloc_buf 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "openssl" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -779,6 +850,7 @@ dependencies = [ "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "compositing 0.0.1", "devtools 0.0.1", + "devtools_traits 0.0.1", "gfx 0.0.1", "layout 0.0.1", "msg 0.0.1", @@ -882,6 +954,14 @@ dependencies = [ ] [[package]] +name = "user32-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "util" version = "0.0.1" dependencies = [ @@ -923,7 +1003,7 @@ dependencies = [ [[package]] name = "webdriver" version = "0.0.1" -source = "git+https://github.com/jgraham/webdriver-rust.git#906806d51783b5caad89432bf8ce008f2f4968fc" +source = "git+https://github.com/jgraham/webdriver-rust.git#4f543416a269b9d0d7ee5332db489768c2a769dd" dependencies = [ "hyper 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -936,10 +1016,23 @@ dependencies = [ name = "webdriver_server" version = "0.0.1" dependencies = [ + "msg 0.0.1", + "rustc-serialize 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "util 0.0.1", + "uuid 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "webdriver 0.0.1 (git+https://github.com/jgraham/webdriver-rust.git)", ] [[package]] +name = "winapi" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "xlib" version = "0.1.0" source = "git+https://github.com/servo/rust-xlib#715e6f9bb3dfcd925996caedeb77aefb31c2bd65" diff --git a/ports/gonk/README.md b/ports/gonk/README.md index 58060cf7294..fbdfb3e8ef7 100644 --- a/ports/gonk/README.md +++ b/ports/gonk/README.md @@ -4,9 +4,19 @@ Follow the steps [here](https://github.com/servo/servo/wiki/Building-for-Android) for setting up the Android NDK and toolchain. + +## Bootstrap B2G + +We have a bootstrap of the require B2G prebuilt binaries, assuming that you are targeting a Flame device. + +``` +curl https://servo-rust.s3.amazonaws.com/B2G/B2G.tgz +tar zxvf B2G.tgz +``` + ## Build B2G -Note: this will take a long time and will take around 20GB of space +If you are not using a Flame or just would like to have a local build of the binaries, you can also build B2G locally. Note: this will take a long time and will take around 20GB of space Disable the screen timeout on the device, and connect to wifi. Also connect it to your computer with remote debugging enabled. @@ -32,8 +42,7 @@ Then run ## Build B2S -Either set the corresponding `b2g` key in `.servobuild` to the path to the B2G clone (along with), or set the `$GONKDIR` -environment variable. +Either set the corresponding `b2g` key in `.servobuild` to the path to the B2G bootstrap or clone (along with), or set the `$GONKDIR` environment variable. Do the same for the `ndk` and `toolchain` keys (`$ANDROID_NDK` and `$ANDROID_TOOLCHAIN` respectively) diff --git a/ports/gonk/fake-ld.sh b/ports/gonk/fake-ld.sh index ab18f01ec73..a03caea6322 100755 --- a/ports/gonk/fake-ld.sh +++ b/ports/gonk/fake-ld.sh @@ -1,2 +1,2 @@ #!/bin/bash -arm-linux-androideabi-g++ $@ $LDFLAGS -pie -lGLESv2 -lsupc++ -L$GONKDIR/prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/ +arm-linux-androideabi-g++ $@ $LDFLAGS -pie -lGLESv2 -lsupc++ -L$GONKDIR/prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/ -L$GONKDIR/backup-flame/system/lib/ diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index ad8e58d04c2..285f24d2534 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -1,5 +1,6 @@ from __future__ import print_function, unicode_literals +import sys import os import os.path as path import subprocess @@ -16,6 +17,48 @@ from servo.command_base import CommandBase, cd def is_headless_build(): return int(os.getenv('SERVO_HEADLESS', 0)) == 1 +# Function to generate desktop notification once build is completed & limit exceeded! +def notify(elapsed): + if elapsed < 300: + return + + if sys.platform.startswith('linux'): + try: + import dbus + bus = dbus.SessionBus() + notify_obj = bus.get_object('org.freedesktop.Notifications', '/org/freedesktop/Notifications') + method = notify_obj.get_dbus_method('Notify', 'org.freedesktop.Notifications') + method('Servo Build System', 0, '', ' Servo build complete!', '', [], [], -1) + except: + print("[Warning] Could not generate notification! Please make sure that the python dbus module is installed!") + + elif sys.platform.startswith('win'): + try: + from ctypes import Structure, windll, POINTER, sizeof + from ctypes.wintypes import DWORD, HANDLE, WINFUNCTYPE, BOOL, UINT + class FLASHWINDOW(Structure): + _fields_ = [("cbSize", UINT), + ("hwnd", HANDLE), + ("dwFlags", DWORD), + ("uCount", UINT), + ("dwTimeout", DWORD)] + FlashWindowExProto = WINFUNCTYPE(BOOL, POINTER(FLASHWINDOW)) + FlashWindowEx = FlashWindowExProto(("FlashWindowEx", windll.user32)) + FLASHW_CAPTION = 0x01 + FLASHW_TRAY = 0x02 + FLASHW_TIMERNOFG = 0x0C + params = FLASHWINDOW(sizeof(FLASHWINDOW), + windll.kernel32.GetConsoleWindow(), + FLASHW_CAPTION | FLASHW_TRAY | FLASHW_TIMERNOFG, 3, 0) + FlashWindowEx(params) + except: + print("[Warning] Could not generate notification! Please make sure that the required libraries are installed!") + + elif sys.platform.startswith('darwin'): + # Notification code for Darwin here! For the time being printing simple msg + print("[Warning] : Darwin System! Notifications not supported currently!") + + @CommandProvider class MachCommands(CommandBase): @Command('build', @@ -102,6 +145,9 @@ class MachCommands(CommandBase): env=env, cwd=self.servo_crate()) elapsed = time() - build_start + # Generate Desktop Notification if elapsed-time > some threshold value + notify(elapsed) + print("Build completed in %0.2fs" % elapsed) return status @@ -135,6 +181,9 @@ class MachCommands(CommandBase): env=self.build_env()) elapsed = time() - build_start + # Generate Desktop Notification if elapsed-time > some threshold value + notify(elapsed) + print("CEF build completed in %0.2fs" % elapsed) return ret @@ -170,6 +219,9 @@ class MachCommands(CommandBase): ret = subprocess.call(["cargo", "build"] + opts, env=env) elapsed = time() - build_start + # Generate Desktop Notification if elapsed-time > some threshold value + notify(elapsed) + print("Gonk build completed in %0.2fs" % elapsed) return ret diff --git a/python/servo/devenv_commands.py b/python/servo/devenv_commands.py index cab3f7ba81f..7caac6e33bd 100644 --- a/python/servo/devenv_commands.py +++ b/python/servo/devenv_commands.py @@ -31,6 +31,15 @@ class MachCommands(CommandBase): return subprocess.call(['cargo'] + params, env=self.build_env()) + @Command('cargo-update', + description='Same as update-cargo', + category='devenv') + @CommandArgument( + 'params', default=None, nargs='...', + help='Command-line arguments to be passed through to cargo update') + def cargo_update(self, params=None): + self.update_cargo(params) + @Command('update-cargo', description='Update Cargo dependencies', category='devenv') diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index e538c79c789..b93d3689700 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -64,7 +64,6 @@ class MachCommands(CommandBase): test_dirs = [ # path, mach test command, optional flag for path argument - (path.join("tests", "content"), "test-content", None), (path.join("tests", "wpt"), "test-wpt", None), (path.join("tests", "ref"), "test-ref", ["--name"]), ] @@ -93,7 +92,7 @@ class MachCommands(CommandBase): return self.infer_test_by_dir(params) test_start = time() - for t in ["tidy", "ref", "content", "wpt", "css", "unit"]: + for t in ["tidy", "ref", "wpt", "css", "unit"]: Registrar.dispatch("test-%s" % t, context=self.context) elapsed = time() - test_start @@ -163,23 +162,10 @@ class MachCommands(CommandBase): @Command('test-content', description='Run the content tests', category='testing') - @CommandArgument('test_name', default=None, nargs="?", - help="Only run tests that match this pattern") - def test_content(self, test_name=None): - self.ensure_bootstrapped() - self.ensure_built_tests() - test_path = path.join(self.context.topdir, "tests", "content") - test_args = ["--source-dir=%s" % test_path] - - if test_name is not None: - test_args.append(test_name) - - test_start = time() - ret = self.run_test("contenttest", test_args) - elapsed = time() - test_start - - print("Content tests completed in %0.2fs" % elapsed) - return ret + def test_content(self): + print("Content tests have been replaced by web-platform-tests under " + "tests/wpt/mozilla/.") + return 0 @Command('test-tidy', description='Run the source code tidiness check', diff --git a/resources/iso-8859-8.css b/resources/iso-8859-8.css index fd97ef5807f..3651061c391 100644 --- a/resources/iso-8859-8.css +++ b/resources/iso-8859-8.css @@ -1,6 +1,6 @@ /* -https://html.spec.whatwg.org/multipage/rendering.html#bidi-rendering +https://html.spec.whatwg.org/multipage/#bidi-rendering > When the document's character encoding is ISO-8859-8, > the following rules are additionally expected to apply, following [user-agent.css] diff --git a/resources/presentational-hints.css b/resources/presentational-hints.css index b3b4d2a5dd1..47404a5db0b 100644 --- a/resources/presentational-hints.css +++ b/resources/presentational-hints.css @@ -1,5 +1,5 @@ /* -https://html.spec.whatwg.org/multipage/rendering.html#presentational-hints +https://html.spec.whatwg.org/multipage/#presentational-hints */ @namespace url(http://www.w3.org/1999/xhtml); @@ -9,7 +9,7 @@ pre[wrap] { white-space: pre-wrap; } /* FIXME: also "align descendants" -https://html.spec.whatwg.org/multipage/rendering.html#align-descendants +https://html.spec.whatwg.org/multipage/#align-descendants */ center, div[align=center i], div[align=middle i] { text-align: center; } div[align=left i] { text-align: left; } @@ -240,7 +240,7 @@ applet, embed, iframe, img, input[type=image i], object, video Extra ol > li - https://html.spec.whatwg.org/multipage/semantics.html#ordinal-value + https://html.spec.whatwg.org/multipage/#ordinal-value col span colgroup (if not col child) @@ -253,7 +253,7 @@ Extra text-align: center; } - https://html.spec.whatwg.org/multipage/rendering.html#rendered-legend + https://html.spec.whatwg.org/multipage/#rendered-legend */ diff --git a/resources/quirks-mode.css b/resources/quirks-mode.css index 4ba71bb6392..284c877358a 100644 --- a/resources/quirks-mode.css +++ b/resources/quirks-mode.css @@ -1,6 +1,6 @@ /* -https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3 +https://html.spec.whatwg.org/multipage/#flow-content-3 > In quirks mode, the following rules are also expected to apply: @@ -23,7 +23,7 @@ table { } -/* FIXME: https://html.spec.whatwg.org/multipage/rendering.html#margin-collapsing-quirks */ +/* FIXME: https://html.spec.whatwg.org/multipage/#margin-collapsing-quirks */ input:not([type=image]), textarea { box-sizing: border-box; } diff --git a/resources/quotes.css b/resources/quotes.css index 2b1b7470b16..2cbb343bc4b 100644 --- a/resources/quotes.css +++ b/resources/quotes.css @@ -1,6 +1,6 @@ /* -https://html.spec.whatwg.org/multipage/rendering.html#quotes +https://html.spec.whatwg.org/multipage/#quotes > This block is automatically generated from the Unicode Common Locale Data Repository. > http://cldr.unicode.org/ diff --git a/resources/user-agent.css b/resources/user-agent.css index 46c5787783a..0971ee8eee4 100644 --- a/resources/user-agent.css +++ b/resources/user-agent.css @@ -1,5 +1,5 @@ /* -https://html.spec.whatwg.org/multipage/rendering.html#form-controls +https://html.spec.whatwg.org/multipage/#form-controls */ @namespace url(http://www.w3.org/1999/xhtml); diff --git a/support/android-rs-glue b/support/android-rs-glue -Subproject 34f588aace4d05ce42f4ca605d5470df8fdd236 +Subproject 5a68056599fb498b0cf3715fd359894825e3b85 diff --git a/support/not-the-toml-you-re-looking-for.rs b/support/not-the-toml-you-re-looking-for.rs deleted file mode 100644 index caf7bde3edd..00000000000 --- a/support/not-the-toml-you-re-looking-for.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - ::std::os::set_exit_status(1); - let _ = ::std::old_io::stderr().write(br" - - This is not the `Cargo.toml` file you're looking for. - Invoke Cargo through mach instead, e.g. `./mach build`. - -"); -} diff --git a/tests/content/harness.js b/tests/content/harness.js deleted file mode 100644 index 452c72fa67d..00000000000 --- a/tests/content/harness.js +++ /dev/null @@ -1,106 +0,0 @@ -function _oneline(x) { - var i = x.indexOf("\n"); - return (i == -1) ? x : (x.slice(0, i) + "..."); -} - -var _expectations = 0; -var _tests = 0; -function expect(num) { - _expectations = num; -} - -function _fail(s, m) { - _tests++; - // string split to avoid problems with tests that end up printing the value of window._fail. - window.alert(_oneline("TEST-UNEXPECTED" + "-FAIL | " + s + ": " + m)); -} - -function _pass(s, m) { - _tests++; - window.alert(_oneline("TEST-PASS | " + s + ": " + m)); -} - -function _printer(opstr, op) { - return function (a, b, msg) { - var f = op(a,b) ? _pass : _fail; - if (!msg) msg = ""; - f(a + " " + opstr + " " + b, msg); - }; -} - -var is = _printer("===", function (a,b) { return a === b; }); -var is_not = _printer("!==", function (a,b) { return a !== b; }); -var is_a = _printer("is a", function (a,b) { return a instanceof b; }); -var is_not_a = _printer("is not a", function (a,b) { return !(a instanceof b); }); -var is_in = _printer("is in", function (a,b) { return a in b; }); -var is_not_in = _printer("is not in", function (a,b) { return !(a in b); }); -var as_str_is = _printer("as string is", function (a,b) { return String(a) == b; }); -var lt = _printer("<", function (a,b) { return a < b; }); -var gt = _printer(">", function (a,b) { return a > b; }); -var leq = _printer("<=", function (a,b) { return a <= b; }); -var geq = _printer(">=", function (a,b) { return a >= b; }); -var starts_with = _printer("starts with", function (a,b) { return a.indexOf(b) == 0; }); - -function is_function(val, name) { - starts_with(String(val), "function " + name + "("); -} - -function should_throw(f) { - try { - f(); - _fail("operation should have thrown but did not"); - } catch (x) { - _pass("operation successfully threw an exception", x.toString()); - } -} - -function should_not_throw(f) { - try { - f(); - _pass("operation did not throw an exception"); - } catch (x) { - _fail("operation should have not thrown", x.toString()); - } -} - -function check_selector(elem, selector, matches) { - is(elem.matches(selector), matches); -} - -function check_disabled_selector(elem, disabled) { - check_selector(elem, ":disabled", disabled); - check_selector(elem, ":enabled", !disabled); -} - -var _test_complete = false; -var _test_timeout = 10000; //10 seconds -function finish() { - if (_test_complete) { - _fail('finish called multiple times'); - } - if (_expectations > _tests) { - _fail('expected ' + _expectations + ' tests, fullfilled ' + _tests); - } - _test_complete = true; - window.close(); -} - -function _test_timed_out() { - if (!_test_complete) { - _fail('test timed out (' + _test_timeout/1000 + 's)'); - finish(); - } -} - -setTimeout(_test_timed_out, _test_timeout); - -var _needs_finish = false; -function waitForExplicitFinish() { - _needs_finish = true; -} - -addEventListener('load', function() { - if (!_needs_finish) { - finish(); - } -}); diff --git a/tests/content/test_DOMParser.html b/tests/content/test_DOMParser.html deleted file mode 100644 index 1928863d8d5..00000000000 --- a/tests/content/test_DOMParser.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> -is_function(DOMParser, "DOMParser"); -let parser = new DOMParser(); -is_a(parser, DOMParser); -is_a(parser.parseFromString("", "text/html"), Document); -</script> -</head> -</html> diff --git a/tests/content/test_Event.html b/tests/content/test_Event.html deleted file mode 100644 index 267983f59ef..00000000000 --- a/tests/content/test_Event.html +++ /dev/null @@ -1,16 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> -is_function(Event, "Event"); - -let ev = new Event("foopy", {cancelable: true}); -is_a(ev, Event); - -is(ev.type, 'foopy'); -is(ev.defaultPrevented, false); -ev.preventDefault(); -is(ev.defaultPrevented, true); -</script> -</head> -</html> diff --git a/tests/content/test_MouseEvent.html b/tests/content/test_MouseEvent.html deleted file mode 100644 index 89173bbe6cc..00000000000 --- a/tests/content/test_MouseEvent.html +++ /dev/null @@ -1,16 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> -is_function(MouseEvent, "MouseEvent"); - -let ev = new MouseEvent("press", {bubbles: true, screenX: 150, detail: 100}); - -is_a(ev, Event); -is_a(ev, UIEvent); -is_a(ev, MouseEvent); -is(ev.screenX, 150); -is(ev.detail, 100); -</script> -</head> -</html> diff --git a/tests/content/test_blob.html b/tests/content/test_blob.html deleted file mode 100644 index a9d5d69098d..00000000000 --- a/tests/content/test_blob.html +++ /dev/null @@ -1,43 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - <script> - var testData = ['<a id="a"><b id="b">hey!</b></a>']; - var b = new Blob(testData); // the blob - is(b.size, 32); - is(b.type, ""); - - var bs = b.slice(0, 5); - is(bs.size, 5); - is(b.type, ""); - - var bc = new Blob(testData, {type:"text/plain"}); // the blob - is(bc.size, 32); - is(bc.type, "text/plain"); - - var bss = new Blob(testData, {type:" text/plain "}); // spaces - is(bss.size, 32); - is(bss.type, " text/plain "); - - var bcs = bc.slice(0, 7); - is(bcs.size, 7); - is(bcs.type, ""); - - var bcsc = bc.slice(0, 7, "text/xml"); - is(bcsc.size, 7); - is(bcsc.type, "text/xml"); - - var bu = new Blob(testData, {type:"TEXT/PLAIN"}); // the blob - is(bu.size, 32); - is(bu.type, "text/plain"); - - var bj = new Blob(testData, {type:"☃"}); // the blob - is(bj.size, 32); - is(bj.type, ""); - - var bjs = bj.slice(0, 7, "☃"); - is(bjs.size, 7); - is(bjs.type, ""); - </script> - </head> -</html> diff --git a/tests/content/test_body_listener.html b/tests/content/test_body_listener.html deleted file mode 100644 index 03dd253c47d..00000000000 --- a/tests/content/test_body_listener.html +++ /dev/null @@ -1,19 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> - waitForExplicitFinish(); - function check_onload(listener) { - is(listener, window); - var ev = new Event('click', {bubbles: true, cancelable: true}); - document.body.dispatchEvent(ev); - } - function check_onclick(listener) { - is(listener, document.body); - finish(); - } -</script> -</head> -<body onload="check_onload(this)" onclick="check_onclick(this)"> -</body> -</html> diff --git a/tests/content/test_characterdata.html b/tests/content/test_characterdata.html deleted file mode 100644 index 7fde5c5f28b..00000000000 --- a/tests/content/test_characterdata.html +++ /dev/null @@ -1,44 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <p>This is the character data</p> - </body> - <script> - var a = document.getElementsByTagName('p')[0].childNodes[0]; - is(a.data, "This is the character data"); - // append test utf8 - a.appendData(", append more 資料,測試資料"); - is(a.data, "This is the character data, append more 資料,測試資料"); - - // length test utf8 - is(a.length, 47); - - // insert test non-utf8 - a.insertData(26, " test"); - is(a.data, "This is the character data test, append more 資料,測試資料"); - // insert test utf8 - a.insertData(48, "更多"); - is(a.data, "This is the character data test, append more 資料,更多測試資料"); - - // delete test non-utf8 - a.deleteData(40, 5); - is(a.data, "This is the character data test, append 資料,更多測試資料"); - // delete test utf8 - a.deleteData(45, 2); - is(a.data, "This is the character data test, append 資料,更多資料"); - - // replace test non-utf8 - a.replaceData(33, 6, "other"); - is(a.data, "This is the character data test, other 資料,更多資料"); - // replace test non-utf8 - a.replaceData(44, 2, "文字"); - is(a.data, "This is the character data test, other 資料,更多文字"); - - // substring test non-utf8 - is(a.substringData(12, 4), "char"); - // substring test utf8 - is(a.substringData(39, 2), "資料"); - </script> -</html> diff --git a/tests/content/test_click_prevent.html b/tests/content/test_click_prevent.html deleted file mode 100644 index 1636080e0af..00000000000 --- a/tests/content/test_click_prevent.html +++ /dev/null @@ -1,18 +0,0 @@ -<html> -<head> -<script src="./harness.js"></script> -<a id="foo" href="/nonexistent">test link</a> -<script> -var link = document.getElementById('foo'); -link.addEventListener('click', function(ev) { - ev.preventDefault(); -}); -var ev = new Event('click', {bubbles: true, cancelable: true}); -link.dispatchEvent(ev); -setTimeout(function() { - is(true, true, "load probably would have occurred by now"); - finish(); -}, 500); -</script> -</head> -</html> diff --git a/tests/content/test_collections.html b/tests/content/test_collections.html deleted file mode 100644 index ce32d838664..00000000000 --- a/tests/content/test_collections.html +++ /dev/null @@ -1,143 +0,0 @@ -<html> -<head> -<meta charset="utf-8"> -<title>test_binding - page </title> -<base href="./"></base> -<script src="harness.js"></script> -</head> -<body> - -<div id="first" name="test">fffff<br><br><br><br>fffffffffffffffff</div> -<div id="second">ggg</div> -<span id="third" name="test">hhhhhhhh</span> -<div id="fourth">iiiiiiiiiiiiiiiiiii</div> -<a href="http://www.mozilla.org"></a> -<img src="test.jpg"/> -<embed></embed> -<form> - <fieldset> - <legend>legend</legend> - <label for="">label<input type="text" value="input" /></label> - </fieldset> -</form> -<hr /> -<canvas/> -<p>pppppppppp</p> -<q>qqqqqqqqqqqqqqqqqqqqqqqqqqq</q> -<progress max="100" value="80">80%</progress> -<applet></applet> -<input type="text" value="input"/> -<iframe></iframe> -<ol type="1"> - <li>li</li> -</ol> -<table> - <caption>sample table</caption> - <colgroup> - <col/> - </colgroup> - <tbody> - <tr><th>head</th></tr> - <tr><td>data</td></tr> - </tbody> -</table> -<section>section</section> -<aside>aside</aside> -<b>b</b> -<i>i</i> -<small>small</small> -<textarea>textarea</textarea> -<time datetime="2014-02-14">Valentines day</time> -<area></area> -<data></data> -<dialog></dialog> -<template></template> -<pre>pre</pre> -<audio> - <source src="horse.ogg" type="audio/ogg"> - <source src="horse.mp3" type="audio/mpeg"> -</audio> -<video src=""> - <track></track> -</video> - -<foo-á>hi</foo-á> - -<script> -function check_collection(obj, num, classes, name) { - is_a(obj, HTMLCollection); - is(obj.length, num); - is(obj[obj.length], undefined); - - if (classes === undefined) - return; - - classes = [Element, HTMLElement].concat(classes); - - for (var i=0; i<obj.length; i++) { - is_not(obj[i], undefined); - is(obj[i].tagName, name); - for (var j=0; j<classes.length; j++) { - is_a(obj[i], classes[j]); - } - } -} - -function check_tag(tagname, num, classes, tagname_upper) { - if (tagname_upper === undefined) - tagname_upper = tagname.toUpperCase(); - check_collection(document.getElementsByTagName(tagname), num, classes, tagname_upper); -} - -check_collection(document.links, 1, [HTMLAnchorElement], "A"); -check_collection(document.images, 1, [HTMLImageElement], "IMG"); -check_collection(document.embeds, 1, [HTMLEmbedElement], "EMBED"); -check_collection(document.plugins, 1, [HTMLEmbedElement], "EMBED"); -check_collection(document.scripts, 2, [HTMLScriptElement], "SCRIPT"); -check_collection(document.applets, 1, [HTMLAppletElement], "APPLET"); -check_collection(document.forms, 1, [HTMLFormElement], "FORM"); - -check_collection(document.getElementsByTagName("nosuchtag"), 0); - -check_tag("section", 1, []); -check_tag("aside", 1, []); -check_tag("b", 1, []); -check_tag("i", 1, []); -check_tag("small", 1, []); -check_tag("head", 1, [HTMLHeadElement]); -check_tag("div", 3, [HTMLDivElement]); -check_tag("iframe", 1, [HTMLIFrameElement]); -check_tag("body", 1, [HTMLBodyElement]); -check_tag("area", 1, [HTMLAreaElement]); -check_tag("base", 1, [HTMLBaseElement]); -check_tag("data", 1, [HTMLDataElement]); -check_tag("dialog", 1, [HTMLDialogElement]); -check_tag("ol", 1, [HTMLOListElement]); -check_tag("canvas", 1, [HTMLCanvasElement]); -check_tag("source", 2, [HTMLSourceElement]); -check_tag("time", 1, [HTMLTimeElement]); -check_tag("caption", 1, [HTMLTableCaptionElement]); -check_tag("textarea", 1, [HTMLTextAreaElement]); -check_tag("q", 1, [HTMLQuoteElement]); -check_tag("th", 1, [HTMLTableCellElement, HTMLTableHeaderCellElement]); -check_tag("td", 1, [HTMLTableCellElement, HTMLTableDataCellElement]); -check_tag("col", 1, [HTMLTableColElement]); -check_tag("colgroup", 1, [HTMLTableColElement]); -check_tag("input", 2, [HTMLInputElement]); -check_tag("li", 1, [HTMLLIElement]); -check_tag("progress", 1, [HTMLProgressElement]); -check_tag("template", 1, [HTMLTemplateElement]); -check_tag("pre", 1, [HTMLPreElement]); -check_tag("legend", 1, [HTMLLegendElement]); -check_tag("label", 1, [HTMLLabelElement]); -check_tag("track", 1, [HTMLTrackElement]); -check_tag("audio", 1, [HTMLMediaElement, HTMLAudioElement]); -check_tag("video", 1, [HTMLMediaElement, HTMLVideoElement]); - -// Test non-ASCII tag names. Uppercasing is ASCII-only per spec: -// http://dom.spec.whatwg.org/#dom-element-tagname -check_tag("foo-á", 1, [HTMLUnknownElement], "FOO-á"); -</script> -</body> -</html> diff --git a/tests/content/test_create_element.html b/tests/content/test_create_element.html deleted file mode 100644 index ede3e21814b..00000000000 --- a/tests/content/test_create_element.html +++ /dev/null @@ -1,18 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> - <script> - var elem = document.createElement("foo"); - is(elem.tagName, "FOO"); - var elem = document.createElement("p"); - is_a(elem, HTMLParagraphElement); - var elem = document.createElement("sPAn"); - is_a(elem, HTMLSpanElement); - var text = document.createTextNode("hello"); - is_a(text, Text); - </script> -</body> -</html> diff --git a/tests/content/test_documentElement.html b/tests/content/test_documentElement.html deleted file mode 100644 index 4bb858e931e..00000000000 --- a/tests/content/test_documentElement.html +++ /dev/null @@ -1,12 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> -is_a(window, Window); -is_a(document.documentElement, HTMLHtmlElement); -is_a(document.documentElement.firstChild, HTMLHeadElement); -is(document.documentElement.nextSibling, null); -is_a(document, Document); -</script> -</head> -</html> diff --git a/tests/content/test_document_activeElement.html b/tests/content/test_document_activeElement.html deleted file mode 100644 index fee51456282..00000000000 --- a/tests/content/test_document_activeElement.html +++ /dev/null @@ -1,18 +0,0 @@ -<!doctype html> -<html> - <head > - <title></title> - <script src="harness.js"></script> - </head> - <body> - <input id="foo" type="text"></input> - <script> - is_not(document.activeElement, null, "test_1.1, document.activeElement"); - is(document.activeElement, document.body, "test_1.2, document.activeElement"); - - document.getElementById('foo').focus(); - is_not(document.activeElement, null, "test_2.1, document.activeElement"); - is(document.activeElement, document.getElementById("foo"), "test_2.2, document.activeElement"); - </script> - </body> -</html> diff --git a/tests/content/test_document_body.html b/tests/content/test_document_body.html deleted file mode 100644 index ebe60a2ad93..00000000000 --- a/tests/content/test_document_body.html +++ /dev/null @@ -1,71 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <script> - // test1: existing document's body - { - is_not(document.body, null, "test1-0, existing document's body"); - is_a(document.body, HTMLBodyElement, "test1-1, exising document's body"); - is(document.body && document.body.tagName, "BODY", "test1-2, existing document's body"); - } - - // test2: replace document's body with new body - { - let new_body = document.createElement("body"); - is_not(new_body, null, "test2-0, replace document's body with new body"); - document.body = new_body; - is(new_body, document.body, "test2-1, replace document's body with new body"); - } - - // test3: replace document's body with new frameset - { - let new_frameset = document.createElement("frameset"); - is_not(new_frameset, null, "test2-0, replace document's body with new frameset"); - document.body = new_frameset; - is(new_frameset, document.body, "test2-1, replace document's body with new frameset"); - } - - // test4: append an invalid element to a new document - { - let new_document = new Document(); - new_document.appendChild(new_document.createElement("html")); - let new_div = new_document.createElement("div"); - - is_not(new_div, null, "test4-0, append an invalid element to a new document"); - - should_throw(function() { - new_document.body = new_div; - }); - is(new_document.body, null, "test4-1, append an invalid element to a new document"); - } - - // test5: append body to a new document - { - let new_document = document.implementation.createHTMLDocument(); - let new_body = new_document.createElement("body"); - - is_not(new_body, null, "test5-0, append body to a new document"); - is_a(new_body, HTMLBodyElement, "test5-1, append body to a new document"); - is(new_body && new_body.tagName, "BODY", "test5-2, append body to a new document"); - - new_document.body = new_body; - is(new_document.body, new_body, "test5-3, append body to a new document"); - } - - // test6: append frameset to a new document - { - let new_document = document.implementation.createHTMLDocument(); - let new_frameset = new_document.createElement("frameset"); - - is_not(new_frameset, null, "test6-0, append frameset to a new document"); - is_a(new_frameset, HTMLFrameSetElement, "test6-1, append frameset to a new document"); - is(new_frameset && new_frameset.tagName, "FRAMESET", "test6-2, append frameset to a new document"); - - new_document.body = new_frameset; - is(new_document.body, new_frameset, "test6-3, append frameset to a new document"); - } - </script> - </body> -</html> diff --git a/tests/content/test_document_characterSet.html b/tests/content/test_document_characterSet.html deleted file mode 100644 index 4e150c682e8..00000000000 --- a/tests/content/test_document_characterSet.html +++ /dev/null @@ -1,19 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: characterSet - { - is(document.characterSet, "UTF-8", "test1-0, characterSet"); - - var xmldoc = new Document; - is(xmldoc.characterSet, "UTF-8", "test2-1, characterSet"); - - var htmldoc = document.implementation.createHTMLDocument("title"); - is(htmldoc.characterSet, "UTF-8", "test2-2, characterSet"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_characterSet_default.html b/tests/content/test_document_characterSet_default.html deleted file mode 100644 index 2c234636519..00000000000 --- a/tests/content/test_document_characterSet_default.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: default characterSet - { - // FIXME: https://github.com/mozilla-servo/libhubbub/issues/5 - is(document.characterSet, "UTF-8", "test1-0, default characterSet"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_characterSet_invalid.html b/tests/content/test_document_characterSet_invalid.html deleted file mode 100644 index 15ab99519c2..00000000000 --- a/tests/content/test_document_characterSet_invalid.html +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE html> -<meta charset="unknown-charset"> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: unknown charset - { - is(document.characterSet, "UTF-8", "test1-0, unknown charset"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_characterSet_long.html.disabled b/tests/content/test_document_characterSet_long.html.disabled deleted file mode 100644 index abf547127a8..00000000000 --- a/tests/content/test_document_characterSet_long.html.disabled +++ /dev/null @@ -1,15 +0,0 @@ -<!DOCTYPE html> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: long charset - { - is(document.characterSet, "windows-1252", "test1-0, long charset"); - } - - finish(); - </script> - </head> -</html> diff --git a/tests/content/test_document_characterSet_short.html.disabled b/tests/content/test_document_characterSet_short.html.disabled deleted file mode 100644 index 358d4f8ba74..00000000000 --- a/tests/content/test_document_characterSet_short.html.disabled +++ /dev/null @@ -1,15 +0,0 @@ -<!DOCTYPE html> -<meta charset="iso-8859-1"> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: short charset - { - is(document.characterSet, "windows-1252", "test1-0, short charset"); - } - - finish(); - </script> - </head> -</html> diff --git a/tests/content/test_document_compatMode_loose.html b/tests/content/test_document_compatMode_loose.html deleted file mode 100644 index da538636bb8..00000000000 --- a/tests/content/test_document_compatMode_loose.html +++ /dev/null @@ -1,12 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: Loose HTML - { - is(document.compatMode, "BackCompat", "test1-0, Loose HTML"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_compatMode_strict.html b/tests/content/test_document_compatMode_strict.html deleted file mode 100644 index b28816cc60f..00000000000 --- a/tests/content/test_document_compatMode_strict.html +++ /dev/null @@ -1,12 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: Strict HTML - { - is(document.compatMode, "CSS1Compat", "test1-0, Strict HTML"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_contenttype.html b/tests/content/test_document_contenttype.html deleted file mode 100644 index 73bf7f0217a..00000000000 --- a/tests/content/test_document_contenttype.html +++ /dev/null @@ -1,20 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: HTML document - { - is_a(document, Document, "test1-0, HTML document"); - is(document.contentType, "text/html", "test1-1, HTML document"); - } - - // test2: XML document - { - var doc = new Document; - is_a(doc, Document, "test2-0, XML document"); - is(doc.contentType, "application/xml", "test2-1, XML document"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_datalist_options.html b/tests/content/test_document_datalist_options.html deleted file mode 100644 index 140a253a761..00000000000 --- a/tests/content/test_document_datalist_options.html +++ /dev/null @@ -1,19 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - </head> - <datalist id="id"> - <option value="A"> - <option value="B"> - <p>P</p> - <div>DIV</div> - <option value="C"> - </datalist> - <script> - var datalist = document.getElementById("id"); - is(datalist.options.length, 3); - is_a(datalist.options[0], HTMLOptionElement); - is_a(datalist.options[1], HTMLOptionElement); - is_a(datalist.options[2], HTMLOptionElement); - </script> -</html> diff --git a/tests/content/test_document_defaultView.html b/tests/content/test_document_defaultView.html deleted file mode 100644 index e5f6d36a433..00000000000 --- a/tests/content/test_document_defaultView.html +++ /dev/null @@ -1,10 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <script> - is(document.defaultView, window); - </script> - </body> -</html> diff --git a/tests/content/test_document_getElementsByName.html b/tests/content/test_document_getElementsByName.html deleted file mode 100644 index 6d45ed6c8bf..00000000000 --- a/tests/content/test_document_getElementsByName.html +++ /dev/null @@ -1,14 +0,0 @@ -<html> -<head > - <title></title> - <script src="harness.js"></script> -</head> -<body> - <div name="foo"></div> - <script> - let nameList = document.getElementsByName("foo"); - is_a(nameList, NodeList); - is_not_a(nameList, HTMLCollection); - </script> -</body> -</html> diff --git a/tests/content/test_document_head.html b/tests/content/test_document_head.html deleted file mode 100644 index 00cff0c885e..00000000000 --- a/tests/content/test_document_head.html +++ /dev/null @@ -1,45 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <script> - // test1: existing document's head - { - is_not(document.head, null, "test1-0, existing document's head"); - is_a(document.head, HTMLHeadElement, "test1-1, exising document's head"); - is(document.head && document.head.tagName, "HEAD", "test1-2, existing document's head"); - } - - // test2: append head to a new document - { - let new_document = new Document(); - new_document.appendChild(new_document.createElement("html")); - let new_head = new_document.createElement("head"); - - is_not(new_head, null, "test2-0, append head to a new document"); - is_a(new_head, HTMLHeadElement, "test2-1, append head to a new document"); - is(new_head && new_head.tagName, "head", "test2-2, append head to a new document"); - - // Document::head is read-only. - new_document.head = new_head; - is(new_document.head, null, "test2-3, append head to a new document"); - - new_document.documentElement.appendChild(new_head); - is(new_document.head, new_head, "test2-4, append head to a new document"); - } - - // test3: head's parent should be document element - { - let new_document = new Document(); - let html = new_document.createElement("html"); - let foo = new_document.createElement("foo"); - let head = new_document.createElement("head"); - new_document.appendChild(html); - html.appendChild(foo); - foo.appendChild(head); - is(new_document.head, null, "test3-0, head's parent should be document element"); - } - </script> - </body> -</html> diff --git a/tests/content/test_document_implementation.html b/tests/content/test_document_implementation.html deleted file mode 100644 index ac51b18f875..00000000000 --- a/tests/content/test_document_implementation.html +++ /dev/null @@ -1,79 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: basic test - { - is_not(document.implementation, null, "test1-0, basic test"); - is_a(document.implementation, DOMImplementation, "test1-1, basic test"); - - var implementation = document.implementation; - is(document.implementation, implementation, "test1-2, basic test"); - } - - // test2: createDocumentType - { - is(document.doctype, null, "test2-0, createDocumentType"); - - var doctype = document.implementation.createDocumentType("html", null, null); - is_a(doctype && doctype, DocumentType, "test2-1, createDocumentType"); - - doctype = document.implementation.createDocumentType("html:html", null, null); - is_a(doctype && doctype, DocumentType, "test2-2, createDocumentType"); - } - - // test3: createHTMLDocument - { - var htmldoc = document.implementation.createHTMLDocument("example title"); - is_not(htmldoc, null, "test3-0, createHTMLDocument"); - is_a(htmldoc, Document, "test3-1, createHTMLDocument"); - is(htmldoc.childNodes.length, 2, "test3-3, createHTMLDocument"); - - is_a(htmldoc.doctype && htmldoc.doctype, DocumentType, "test3-4, createHTMLDocument"); - is(htmldoc.doctype.name, "html", "test3-5, createHTMLDocument"); - - is_a(htmldoc.documentElement && htmldoc.documentElement, HTMLHtmlElement, "test3-6, createHTMLDocument"); - is(htmldoc.documentElement.childNodes.length, 2, "test3-7, createHTMLDocument"); - is(htmldoc.documentElement.tagName, "HTML", "test3-8, createHTMLDocument"); - - is_a(htmldoc.head && htmldoc.head, HTMLHeadElement, "test3-9, createHTMLDocument"); - is(htmldoc.head.tagName, "HEAD", "test3-10, createHTMLDocument"); - is(htmldoc.head, htmldoc.documentElement.childNodes[0], "test3-11, createHTMLDocument"); - is(htmldoc.head.childNodes.length, 1, "test3-12, createHTMLDocument"); - - is_a(htmldoc.head.childNodes[0], HTMLTitleElement, "test3-13, createHTMLDocument"); - is(htmldoc.head.childNodes[0].tagName, "TITLE", "test3-14, createHTMLDocument"); - is(htmldoc.title, "example title", "test3-15, createHTMLDocument"); - - is_a(htmldoc.body && htmldoc.body, HTMLBodyElement, "test3-16, createHTMLDocument"); - is(htmldoc.body.tagName, "BODY", "test3-17, createHTMLDocument"); - is(htmldoc.body, htmldoc.documentElement.childNodes[1], "test3-18, createHTMLDocument"); - is(htmldoc.body.childNodes.length, 0, "test3-19, createHTMLDocument"); - } - - // test4: createDocument - { - var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null); - is_not(doc, null, "test4-0, createDocument"); - is_a(doc, Document, "test4-1, createDocument"); - is(doc.childNodes.length, 1, "test4-2, createDocument"); - is(doc.doctype, null, "test4-3, createDocument"); - is_a(doc.documentElement, HTMLHtmlElement, "test4-4, createDocument"); - - var doctype = document.implementation.createDocumentType("html", null, null); - doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', doctype); - is(doc.childNodes.length, 2, "test4-5, createDocument"); - is(doc.doctype, doctype, "test4-6, createDocument"); - is_a(doc.documentElement, HTMLHtmlElement, "test4-7, createDocument"); - - doctype = document.implementation.createDocumentType( - 'svg:svg', '-//W3C//DTD SVG 1.1//EN', - 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'); - doc = document.implementation.createDocument('http://www.w3.org/2000/svg', 'svg:svg', doctype); - is(doc.childNodes.length, 2, "test4-8, createDocument"); - is(doc.doctype, doctype, "test4-9, createDocument"); - is_a(doc.documentElement, Element, "test4-10, createDocument"); - } - </script> - </head> -</html> diff --git a/tests/content/test_document_readystate.html b/tests/content/test_document_readystate.html deleted file mode 100644 index bf0066908f7..00000000000 --- a/tests/content/test_document_readystate.html +++ /dev/null @@ -1,16 +0,0 @@ -<html> -<head> - <script src="harness.js"></script> -</head> -<body onload="is(document.readyState, 'complete'); is(gNumChanges, 2); finish()"> - <script> - waitForExplicitFinish(); - - gNumChanges = 0; - document.addEventListener('readystatechange', function() { - gNumChanges++; - }, true); - is(document.readyState, "loading"); - </script> -</body> -</html> diff --git a/tests/content/test_document_set_node_value.html b/tests/content/test_document_set_node_value.html deleted file mode 100644 index 6aeb79bc5f7..00000000000 --- a/tests/content/test_document_set_node_value.html +++ /dev/null @@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html> - <script src="harness.js"></script> - <body> - <div id="div" class="div-class">A</div> - <p>P</p> - <script> - is(document.nodeValue, null); - var div = document.getElementById("div"); - is(div.nodeValue, null); - is(div.firstChild.nodeValue, "A"); - div.firstChild.nodeValue = "B"; - is(div.firstChild.nodeValue, "B"); - var commentNode = document.createComment("comment node"); - is(commentNode.nodeValue, "comment node"); - </script> - </body> -</html> diff --git a/tests/content/test_document_title_nontextchildren.html b/tests/content/test_document_title_nontextchildren.html deleted file mode 100644 index 20a74d4587d..00000000000 --- a/tests/content/test_document_title_nontextchildren.html +++ /dev/null @@ -1,8 +0,0 @@ -<html> -<title>x</title> -<script src="harness.js"></script> -<script> -document.head.firstChild.appendChild(document.createElement("foo")); -is(document.title, "x"); -</script> -</html> diff --git a/tests/content/test_document_url.html b/tests/content/test_document_url.html deleted file mode 100644 index cb3aca2b0f1..00000000000 --- a/tests/content/test_document_url.html +++ /dev/null @@ -1,30 +0,0 @@ -<!doctype html> -<html> - <head> - <title></title> - <script src="harness.js"></script> - <script> - // test1: URL & documentURI - { - is_not(document.URL, null, "test1-0, URL & documentURI"); - is_not(document.documentURI, null, "test1-1, URL & documentURI"); - is(document.URL, document.documentURI, "test1-2, URL & documentURI"); - } - - // test2: new document - { - var doc = new Document(); - is(doc.URL, "about:blank", "test2-0, new document"); - } - - // test3: current document - { - var url = document.URL.split("/"); - is(url[0], "file:", "test3-0, current document"); - is(url[url.length-1], "test_document_url.html", "test3-1, current document"); - } - </script> - </head> - <body> - </body> -</html> diff --git a/tests/content/test_domtokenlist.html b/tests/content/test_domtokenlist.html deleted file mode 100644 index 98877ddf840..00000000000 --- a/tests/content/test_domtokenlist.html +++ /dev/null @@ -1,43 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - var div = document.createElement("div"); - var classList = div.classList; - - is(classList.length, 0); - is(classList.item(0), null); - should_throw(function () { - classList.contains(""); - }); - should_throw(function () { - classList.contains(" "); - }); - - var list = ["foo", " foo", "foo ", " foo ", " foo "]; - for(var i = 0; i < list.length; i++) { - div.className = list[i]; - is(div.className, list[i]); - is(classList.length, 1); - is(classList.item(0), "foo"); - is(classList.item(1), null); - is(classList.contains("foo"), true); - is(classList.contains("bar"), false); - } - - list = ["foo bar", " foo bar", " foo bar ", " foo bar "]; - for(var i = 0; i < list.length; i++) { - div.className = list[i]; - is(div.className, list[i]); - is(classList.length, 2); - is(classList.item(0), "foo"); - is(classList.item(1), "bar"); - is(classList.item(2), null); - is(classList.contains("foo"), true); - is(classList.contains("bar"), true); - is(classList.contains("baz"), false); - } - </script> - </head> -</html> diff --git a/tests/content/test_element_attribute.html b/tests/content/test_element_attribute.html deleted file mode 100644 index 3715c4e091d..00000000000 --- a/tests/content/test_element_attribute.html +++ /dev/null @@ -1,64 +0,0 @@ -<html> -<head id="foo"> - <title></title> - <script src="harness.js"></script> -</head> -<body> - <div id="test" foo="bar"></div> - <script> - let test = document.getElementById("test"); - - { - let r1 = test.getAttribute("id"); - is(r1, "test", "test1-0, Element.getAttribute()."); - let r2 = test.getAttribute("foo"); - is(r2, "bar", "test1-1, Element.getAttribute()."); - } - - { - let NAME = "hoge"; - let VALUE = "fuga"; - test.setAttribute(NAME, VALUE); - let r = test.getAttribute(NAME); - is(r, VALUE, "test2. Element.setAttribute()."); - } - - { - let NAME = "foo"; - let VALUE = "mozilla"; - test.setAttribute(NAME, VALUE); - let r = test.getAttribute(NAME); - is(r, VALUE, "test3, attribute update by Element.setAttribute().") - } - - { - test.setAttribute("id", "bar"); - test.removeAttribute("id"); - - let r1 = test.hasAttribute("id"); - is(r1, false, "test4-0, Element.removeAttribute()."); - let r2 = test.getAttribute("id"); - is(r2, null, "test4-1, Element.removeAttribute()."); - } - - { - test.setAttribute("xml:lang", "en"); - - let r1 = test.hasAttribute("xml:lang"); - is(r1, true, "test5-0, Element.setAttribute('xml:lang')."); - let r2 = test.getAttribute("xml:lang"); - is_not(r2, null, "test5-1, Element.setAttribute('xml:lang')."); - } - - should_throw(function () { - test.setAttributeNS("http://example.com", "xmlns", "foo"); - }); - should_throw(function () { - test.setAttributeNS("http://www.w3.org/2000/xmlns/", "attr", "value"); - }); - should_throw(function () { - test.setAttributeNS("http://www.w3.org/2000/xmlns/", "prefix:attr", "value"); - }); - </script> -</body> -</html> diff --git a/tests/content/test_element_classList.html b/tests/content/test_element_classList.html deleted file mode 100644 index 8d61414017b..00000000000 --- a/tests/content/test_element_classList.html +++ /dev/null @@ -1,19 +0,0 @@ -<!-- Remove this and update WPT metadata once DOMTokenList.toggle (#3138) is implemented. --> -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - let div = document.createElement("div"); - div.className = "foo bar"; - - let classList = div.classList; - div.className = ""; - - is(classList.item(0), null, "classList.item(0) must return null when all classes have been removed"); - is(classList[0], undefined, "classList[0] must be undefined when all classes have been removed"); - </script> - </head> - <body> - </body> -</html> diff --git a/tests/content/test_element_matches.html b/tests/content/test_element_matches.html deleted file mode 100644 index 50847e4dcc2..00000000000 --- a/tests/content/test_element_matches.html +++ /dev/null @@ -1,16 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="harness.js"></script> -</head> -<body> - <div id="foo"></div> - - <script> - let test = document.getElementById("foo"); - - is(test.matches("#foo"), true, "test-1"); - is(test.matches("#not-foo"), false, "test-2"); - </script> -</body> -</html> diff --git a/tests/content/test_empty_clientrect.html b/tests/content/test_empty_clientrect.html deleted file mode 100644 index af319a14528..00000000000 --- a/tests/content/test_empty_clientrect.html +++ /dev/null @@ -1,17 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> -var rect = window.document.head.getBoundingClientRect(); -var rects = window.document.head.getClientRects(); -is_a(rect, DOMRect); -is(rect.top, 0); -is(rect.bottom, 0); -is(rect.left, 0); -is(rect.right, 0); -is(rect.width, 0); -is(rect.height, 0); -is(rects.length, 0); -</script> -</head> -</html> diff --git a/tests/content/test_event_dispatch.html b/tests/content/test_event_dispatch.html deleted file mode 100644 index 0ace43d8f28..00000000000 --- a/tests/content/test_event_dispatch.html +++ /dev/null @@ -1,49 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -</head> -<body> -<span>Paragraph containing <div>event listener</div>.</span> -<script> - var bodyTimes = 0; - function bodyListener(ev) { - bodyTimes++; - is(ev.currentTarget, document.getElementsByTagName('body')[0]); - is(ev.target, document.getElementsByTagName('div')[0]); - if (bodyTimes == 1) { - is(ev.eventPhase, ev.CAPTURING_PHASE); - } else if (bodyTimes == 2) { - is(ev.eventPhase, ev.BUBBLING_PHASE); - } - } - - var spanTimes = 0; - function spanListener(ev) { - is(ev.currentTarget, document.getElementsByTagName('span')[0]); - is(ev.target, document.getElementsByTagName('div')[0]); - is(ev.eventPhase, ev.BUBBLING_PHASE); - spanTimes++; - } - - var divTimes = 0; - function divListener(ev) { - var self = document.getElementsByTagName('div')[0]; - is(ev.currentTarget, self); - is(ev.target, self); - is(ev.eventPhase, ev.AT_TARGET); - divTimes++; - } - - document.getElementsByTagName('body')[0].addEventListener("foopy", bodyListener, true); - document.getElementsByTagName('body')[0].addEventListener("foopy", bodyListener, false); - document.getElementsByTagName('span')[0].addEventListener("foopy", spanListener, false); - document.getElementsByTagName('div')[0].addEventListener("foopy", divListener, false); - var ev = new Event('foopy', {bubbles: true}); - is(ev.bubbles, true); - document.getElementsByTagName('div')[0].dispatchEvent(ev); - is(bodyTimes, 2, 'body listener should be called multiple times'); - is(divTimes, 1, 'target listener should be called once'); - is(spanTimes, 1, 'span listener should be called while bubbling'); -</script> -</body> -</html> diff --git a/tests/content/test_event_dispatch_dynamic.html b/tests/content/test_event_dispatch_dynamic.html deleted file mode 100644 index a7daddd4afc..00000000000 --- a/tests/content/test_event_dispatch_dynamic.html +++ /dev/null @@ -1,20 +0,0 @@ -<!DOCTYPE html> -<script src="harness.js"></script> -<b><b><b></b></b></b> -<script> -var sawmiddle = -1; -var sawouter = -1; -var step = 0; -var outerb = document.getElementsByTagName('b')[0]; -var middleb = outerb.firstChild; -var innerb = middleb.firstChild; -outerb.addEventListener("x", function() { - middleb.addEventListener("x", function() { - sawmiddle = step++; - }, true); - sawouter = step++; -}, true); -innerb.dispatchEvent(new Event("x")); -is(sawmiddle, 1); -is(sawouter, 0); -</script> diff --git a/tests/content/test_event_dispatch_order.html b/tests/content/test_event_dispatch_order.html deleted file mode 100644 index 8092a6eeefd..00000000000 --- a/tests/content/test_event_dispatch_order.html +++ /dev/null @@ -1,41 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -</head> -<body> -<div id="foo"></div> -<script> - var sawBubble = false; - var sawCapture = false; - var sawBubbleTwice = false; - function handler(ev) { - is(ev.eventPhase, ev.AT_TARGET); - is(sawBubble, false); - is(sawCapture, false); - sawBubble = true; - } - function handler2(ev) { - is(ev.eventPhase, ev.AT_TARGET); - is(sawBubble, true); - is(sawCapture, false); - sawCapture = true; - } - function handler3(ev) { - is(ev.eventPhase, ev.AT_TARGET); - is(sawBubble, true); - is(sawCapture, true); - sawBubbleTwice = true; - } - - var target = document.getElementById('foo'); - target.addEventListener('foopy', handler, false); - target.addEventListener('foopy', handler2, true); - target.addEventListener('foopy', handler3, false); - var ev = new Event('foopy', {bubbles: true}); - target.dispatchEvent(ev); - is(sawBubble, true); - is(sawCapture, true); - is(sawBubbleTwice, true); -</script> -</body> -</html> diff --git a/tests/content/test_event_handler_syntax_error.html b/tests/content/test_event_handler_syntax_error.html deleted file mode 100644 index 3c58a6b4b80..00000000000 --- a/tests/content/test_event_handler_syntax_error.html +++ /dev/null @@ -1,21 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title></title> - <meta charset="UTF-8"> - <script src="harness.js"></script> -</head> -<body> - <a id="a" onclick="{">link</a> - <script> - var a = document.getElementById("a"); - is(a.onclick, null, "invalid onclick attribute"); - - document.body.setAttribute("onx", "{"); - document.body.setAttribute("ony", "}"); - - is(document.body.getAttribute("onx"), "{"); - is(document.body.getAttribute("ony"), "}"); - </script> -</body> -</html> diff --git a/tests/content/test_focus_blur.html b/tests/content/test_focus_blur.html deleted file mode 100644 index 8c91f2a14a8..00000000000 --- a/tests/content/test_focus_blur.html +++ /dev/null @@ -1,25 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta charset="UTF-8"> - <script src="harness.js"></script> -</head> -<body> - <input id="a"> - <input id="b"> - <script> - var a = document.getElementById("a"); - var b = document.getElementById("b"); - - is(document.activeElement, document.body); - a.focus(); - is(document.activeElement, a); - b.focus(); - is(document.activeElement, b); - a.blur(); - is(document.activeElement, b); - b.blur(); - is(document.activeElement, document.body); - </script> -</body> -</html> diff --git a/tests/content/test_getBoundingClientRect.html b/tests/content/test_getBoundingClientRect.html deleted file mode 100644 index 4e751db844f..00000000000 --- a/tests/content/test_getBoundingClientRect.html +++ /dev/null @@ -1,34 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<style> -div { - position: relative; - top: 100px; - left: 100px; - width: 100px; - height: 100px; -} -</style> -</head> -<body> - <div>my div</div> - <script> - is_function(DOMRect, "DOMRect"); - - var elems = document.getElementsByTagName('div'); - var rect = elems[0].getBoundingClientRect(); - is_a(rect, DOMRect); - - geq(rect.top, 100); - geq(rect.bottom, 200); - geq(rect.left, 100); - geq(rect.right, 200); - - is(rect.width, 100); - is(rect.height, 100); - is(rect.width, rect.right - rect.left); - is(rect.height, rect.bottom - rect.top); - </script> -</body> -</html> diff --git a/tests/content/test_global.html b/tests/content/test_global.html deleted file mode 100644 index b3a0c2dbbba..00000000000 --- a/tests/content/test_global.html +++ /dev/null @@ -1,12 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<script> -is(window, window.window); -is(window, this); -for (var key in this) { - is(this[key], window[key]); -} -</script> -</head> -</html> diff --git a/tests/content/test_htmlfieldsetelement_elements.html b/tests/content/test_htmlfieldsetelement_elements.html deleted file mode 100644 index 45174bf86c5..00000000000 --- a/tests/content/test_htmlfieldsetelement_elements.html +++ /dev/null @@ -1,44 +0,0 @@ -<html> - <script src="harness.js"></script> - <fieldset id="fs"> - <legend>Display</legend> - <input type=radio name=a> - <fieldset> - <button>Click!</button> - </fieldset> - <keygen name="key"> - <textarea> - A - </textarea> - <select> - <option value="1"> A </option> - <option value="2" selected> B </option> - </select> - <form onsubmit="return false" oninput="o.value = a.valueAsNumber + b.valueAsNumber"> - <input name=a type=number step=any> + - <input name=b type=number step=any> = - <output name=c for="a b"></output> - </form> - <figure> - <object type="application/x-java-applet"> - <param name="code" value="MyJavaClass"> - <p>You do not have Java available, or it is disabled.</p> - </object> - <figcaption>My Java Clock</figcaption> - </figure> - </fieldset> - <script> - var fs = document.getElementById("fs"); - is(fs.elements.length, 10); - is_a(fs.elements[0], HTMLInputElement); - is_a(fs.elements[1], HTMLFieldSetElement); - is_a(fs.elements[2], HTMLButtonElement); - is_a(fs.elements[3], HTMLUnknownElement); - is_a(fs.elements[4], HTMLTextAreaElement); - is_a(fs.elements[5], HTMLSelectElement); - is_a(fs.elements[6], HTMLInputElement); - is_a(fs.elements[7], HTMLInputElement); - is_a(fs.elements[8], HTMLOutputElement); - is_a(fs.elements[9], HTMLObjectElement); - </script> -</html> diff --git a/tests/content/test_iframe_contentDocument.html b/tests/content/test_iframe_contentDocument.html deleted file mode 100644 index 93e5c9c8c62..00000000000 --- a/tests/content/test_iframe_contentDocument.html +++ /dev/null @@ -1,27 +0,0 @@ -<html> -<head> -<meta charset="utf8" /> -<script src="harness.js"></script> -<title>Iframe contentDocument test.</title> -</head> -<body> -<iframe src="resources/iframe_contentDocument_inner.html" id="iframe"></iframe> -<script> -waitForExplicitFinish(); - -var timeout = 100; -var iframe = document.getElementById('iframe'); -function test_contentWindow() { - if (!iframe.contentWindow) { - // Iframe not loaded yet, try again. - // No load event for iframe, insert bug number here. - setTimeout(test_contentWindow, timeout); - return; - } - is(iframe.contentDocument.getElementById('test').textContent, 'value'); - finish(); -} -test_contentWindow(); -</script> -</body> -</html> diff --git a/tests/content/test_img_width_height.html b/tests/content/test_img_width_height.html deleted file mode 100644 index 4c1c8e25076..00000000000 --- a/tests/content/test_img_width_height.html +++ /dev/null @@ -1,33 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> - <img src="test.png"/> -<script> -// Testing get/set of image width/height properties -waitForExplicitFinish(); - -var img = window.document.getElementsByTagName("img")[0]; - -function wait_for_img_load(f) { - if (img.width != 0) { - f(); - } else { - window.setTimeout(function() { wait_for_img_load(f) }, 1); - } -} - -wait_for_img_load(function() { - is(img.width, 500); - is(img.height, 378); - img.width = 200; - img.height = 100; - is(img.width, 200); - is(img.height, 100); - finish(); -}); -</script> -</body> -</html> diff --git a/tests/content/test_inline_event_handler.html b/tests/content/test_inline_event_handler.html deleted file mode 100644 index 53ba610f074..00000000000 --- a/tests/content/test_inline_event_handler.html +++ /dev/null @@ -1,10 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -</head> -<body onload="is_a(event, Event); finish()"> -<script> - waitForExplicitFinish(); -</script> -</body> -</html> diff --git a/tests/content/test_lenient_this.html b/tests/content/test_lenient_this.html deleted file mode 100644 index 7e7d27b4300..00000000000 --- a/tests/content/test_lenient_this.html +++ /dev/null @@ -1,26 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - <script> - var handler = function () { }; - document.onreadystatechange = handler; - var obj = {}; - - // test1: basic test - { - var val = Object.getOwnPropertyDescriptor(Document.prototype, "onreadystatechange").get.call(document); - is(val, handler, "test1-0, basic test"); - } - - // test2: Should not throw for attribute marked "[LenientThis]" - { - should_not_throw(function () { - var val = null; - val = Object.getOwnPropertyDescriptor(Document.prototype, "onreadystatechange").get.call(obj); - is(val, undefined, "test2-0, calling getter returns undefined"); - is(Document.prototype.onreadystatechange, undefined, "test2-1, property access returns undefined"); - }); - } - </script> - </head> -</html> diff --git a/tests/content/test_load_event.html b/tests/content/test_load_event.html deleted file mode 100644 index bbf07d699cb..00000000000 --- a/tests/content/test_load_event.html +++ /dev/null @@ -1,36 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -</head> -<body> -<script> - waitForExplicitFinish(); - - var onloads = 0; - function check(ev) { - is_a(ev, Event); - ev.preventDefault(); - is(ev.defaultPrevented, false); - is(ev.target, document); - is(ev.currentTarget, window); - if (onloads == 2) { - finish(); - } - } - - window.onload = function(ev) { - _fail("this inline handler should be overwritten"); - } - window.onload = function(ev) { - onloads++; - is(onloads, 1); - check(ev); - } - addEventListener("load", function(ev) { - onloads++; - is(onloads, 2); - check(ev); - }); -</script> -</body> -</html> diff --git a/tests/content/test_navigator.html b/tests/content/test_navigator.html deleted file mode 100644 index 72cd17ab8f1..00000000000 --- a/tests/content/test_navigator.html +++ /dev/null @@ -1,20 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> -<script> -is(window.navigator, window.navigator); -is_a(window.navigator, Navigator); - -var nav = window.navigator; -is(nav.product, "Gecko"); -is(nav.taintEnabled(), false); -is(nav.appName, "Netscape"); -is(nav.appCodeName, "Mozilla"); -is(nav.platform, ""); -is(nav.appVersion, "4.0"); -</script> -</body> -</html> diff --git a/tests/content/test_node_compareDocumentPosition.html b/tests/content/test_node_compareDocumentPosition.html deleted file mode 100644 index 843d8095262..00000000000 --- a/tests/content/test_node_compareDocumentPosition.html +++ /dev/null @@ -1,35 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - { - var elem = document.createElement("div"); - var other = document.createElement("div"); - is(elem.compareDocumentPosition(elem),0); - - var nonTree = elem.compareDocumentPosition(other); - var prefix = Node.DOCUMENT_POSITION_DISCONNECTED + Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; - is(nonTree == prefix + Node.DOCUMENT_POSITION_FOLLOWING || nonTree == prefix + Node.DOCUMENT_POSITION_PRECEDING, - true); - - elem.appendChild(other); - is(elem.compareDocumentPosition(other), Node.DOCUMENT_POSITION_CONTAINED_BY + Node.DOCUMENT_POSITION_FOLLOWING); - is(other.compareDocumentPosition(elem), Node.DOCUMENT_POSITION_CONTAINS + Node.DOCUMENT_POSITION_PRECEDING); - - var another = document.createElement("div"); - other.appendChild(another); - is(elem.compareDocumentPosition(another), Node.DOCUMENT_POSITION_CONTAINED_BY + Node.DOCUMENT_POSITION_FOLLOWING); - is(another.compareDocumentPosition(elem), Node.DOCUMENT_POSITION_CONTAINS + Node.DOCUMENT_POSITION_PRECEDING); - - var follower = document.createElement("div"); - elem.appendChild(follower); - var preceder = document.createElement("div"); - another.appendChild(preceder); - is(another.compareDocumentPosition(follower), Node.DOCUMENT_POSITION_FOLLOWING); - is(follower.compareDocumentPosition(another), Node.DOCUMENT_POSITION_PRECEDING); - is(follower.compareDocumentPosition(preceder), Node.DOCUMENT_POSITION_PRECEDING); - } - </script> - </head> -</html> diff --git a/tests/content/test_node_contains.html b/tests/content/test_node_contains.html deleted file mode 100644 index 568edf96ebb..00000000000 --- a/tests/content/test_node_contains.html +++ /dev/null @@ -1,23 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: Node.contains - { - var parent = document.createElement("div"); - var child = document.createElement("div"); - var child_of_child = document.createElement("div"); - var other = document.createElement("div"); - - child.appendChild(child_of_child); - parent.appendChild(child); - - is(parent.contains(parent), true, "test1-0, Node.contains"); - is(parent.contains(child), true, "test1-1, Node.contains"); - is(parent.contains(child_of_child), true, "test1-2, Node.contains"); - is(parent.contains(other), false, "test1-3, Node.contains"); - } - </script> - </head> -</html> diff --git a/tests/content/test_node_insertBefore.html b/tests/content/test_node_insertBefore.html deleted file mode 100644 index 1a280b1bb7b..00000000000 --- a/tests/content/test_node_insertBefore.html +++ /dev/null @@ -1,23 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Node.insertBefore</title> - <script src="harness.js"></script> - </head> - <body> - <script type="text/javascript"> - // test1: insertBefore - { - var root = document.createElement("div"); - var after = document.createElement("div"); - var before = document.createElement("div"); - - root.appendChild(after); - - is(root.insertBefore(before, after), before, "test1-0, insertBefore"); - is(root.childNodes[0], before, "test1-1, insertBefore"); - is(root.childNodes[1], after, "test1-2, insertBefore"); - } - </script> - </body> -</html> diff --git a/tests/content/test_node_isEqualNode.html b/tests/content/test_node_isEqualNode.html deleted file mode 100644 index feaeeb2f78a..00000000000 --- a/tests/content/test_node_isEqualNode.html +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - <script> - // test1: simple checks - { - var elem = document.createElement("div"); - var other = document.createElement("div"); - is(elem.isEqualNode(elem), true); - is(elem.isEqualNode(other), true); - is(other.isEqualNode(elem), true); - is(elem.isEqualNode(document), false); - } - - // test2: non-element children - { - var parent_elem = document.createElement("div"); - var child_elem = document.createElement("div"); - parent_elem.appendChild(child_elem); - - var other_parent = document.createElement("div"); - var other_child = document.createElement("div"); - other_parent.appendChild(other_child); - - is(parent_elem.isEqualNode(other_parent), true); - is(child_elem.isEqualNode(other_child), true); - - var child_text = document.createTextNode("lorem ipsum"); - child_elem.appendChild(child_text); - - is(parent_elem.isEqualNode(other_parent), false); - is(child_elem.isEqualNode(other_child), false); - } - </script> - </head> -</html> diff --git a/tests/content/test_node_normalize.html b/tests/content/test_node_normalize.html deleted file mode 100644 index 27f1ccedd5f..00000000000 --- a/tests/content/test_node_normalize.html +++ /dev/null @@ -1,33 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <script> - // test1: Node.normalize - var parent1 = document.createElement("div"); - var child1 = document.createTextNode("aaa"); - var child2 = document.createTextNode(""); - var child3 = document.createTextNode("bb"); - - var parent2 = document.createElement("div"); - - parent1.appendChild(child1); - parent1.appendChild(child2); - parent1.appendChild(child3); - - parent2.appendChild(document.createTextNode("")); - - parent1.normalize(); - parent2.normalize(); - - is(Array.prototype.map.call(parent1.childNodes, function(el) {return el.length}).indexOf(0), -1, "Node.normalize removes empty text nodes"); - is(parent1.childNodes.length, 1, "Node.normalize merges text nodes in one"); - is(parent1.childNodes[0].length, 5, "test 1-2, Node.normalize merges text nodes values"); - is(parent2.childNodes.length, 0, "Node.normalize removes empty text nodes even if there is only one text node"); - is(child2.textContent, "", "Node.normalize doesn't change removed children original content") - is(child3.textContent, "bb", "Node.normalize doesn't change removed children original content") - </script> - </body> -</html> diff --git a/tests/content/test_node_replaceChild.html b/tests/content/test_node_replaceChild.html deleted file mode 100644 index 1ca01e501e7..00000000000 --- a/tests/content/test_node_replaceChild.html +++ /dev/null @@ -1,50 +0,0 @@ -<!doctype html> -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <script> - // test1: 1-to-1 - { - var root = document.createElement("div"); - var elem = document.createElement("div"); - var foo = document.createTextNode("foo"); - var bar = document.createTextNode("bar"); - - elem.appendChild(bar); - is(elem.replaceChild(bar, bar), bar, "test1-0, 1-to-1"); - is(elem.childNodes[0], bar, "test1-1, 1-to-1"); - - root.appendChild(foo); - is(root.replaceChild(bar, foo), foo, "test1-2, 1-to-1"); - is(elem.childNodes.length, 0, "test1-3, 1-to-1"); - is(root.childNodes[0], bar, "test1-4, 1-to-1"); - - elem.appendChild(foo); - is(root.replaceChild(elem, bar), bar, "test1-5, 1-to-1"); - is(root.childNodes[0].childNodes[0], foo, "test1-6, 1-to-1"); - } - - // test2: doctype - { - var doc_doctype = document.doctype; - var new_doctype = document.implementation.createDocumentType("html", null, null); - - is_not(doc_doctype, new_doctype, "test2-0, doctype"); - is(document.replaceChild(new_doctype, doc_doctype), doc_doctype, "test2-1, doctype"); - is(document.doctype, new_doctype, "test2-2, doctype"); - } - - // test3: documentElement - { - var doc_elem = document.documentElement; - var new_elem = document.createElement("html"); - - is_not(doc_elem, new_elem, "test3-0, documentElement"); - is(document.replaceChild(new_elem, doc_elem), doc_elem, "test3-1, documentElement"); - is(document.documentElement, new_elem, "test3-2, documentElement"); - } - </script> - </body> -</html> diff --git a/tests/content/test_parentNode_querySelector.html b/tests/content/test_parentNode_querySelector.html deleted file mode 100644 index 9ab4eb3b1cf..00000000000 --- a/tests/content/test_parentNode_querySelector.html +++ /dev/null @@ -1,69 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <div id="foo"></div> - <div id="foo\bar"></div> - <div id="foo:bar"></div> - <div id="bar" class="myClass"></p> - <script> - { // document.querySelector - let div = document.getElementById("foo"); - is(document.querySelector("#foo"), div); - - div = document.getElementById("foo\\bar"); - is(document.querySelector("#foo\\\\bar"), div); - - div = document.getElementById("foo:bar"); - is(document.querySelector("#foo\\:bar"), div); - - div = document.getElementById("bar"); - is(document.querySelector("div.myClass"), div); - is(document.querySelector("div:nth-of-type(4)"), div); - } - { // element.querySelector - let body = document.body; - let div = document.getElementById("foo"); - is(body.querySelector("#foo"), div); - - div = document.getElementById("foo\\bar"); - is(body.querySelector("#foo\\\\bar"), div); - - div = document.getElementById("foo:bar"); - is(body.querySelector("#foo\\:bar"), div); - - div = document.getElementById("bar"); - is(body.querySelector("div.myClass"), div); - is(body.querySelector("div:nth-of-type(4)"), div); - } - - { // docfrag.querySelector - let docfrag = document.createDocumentFragment(); - - let div = document.createElement("div"); - div.id = "foo"; - div.className = "myClass"; - - let child = document.createElement("div"); - div.appendChild(child); - docfrag.appendChild(div); - - let p = document.createElement("p"); - p.id = "bar"; - p.className = "myClass"; - docfrag.appendChild(p); - - is(docfrag.querySelector("#foo"), div); - is(docfrag.querySelector("div.myClass"), div); - - is(docfrag.querySelector("#bar"), p); - is(docfrag.querySelector("p.myClass"), p); - - is(docfrag.querySelector(".myClass"), div); - is(docfrag.querySelector("div > div"), child); - } - </script> - </body> -</html> diff --git a/tests/content/test_parentnodes.html b/tests/content/test_parentnodes.html deleted file mode 100644 index 51f0f3d1148..00000000000 --- a/tests/content/test_parentnodes.html +++ /dev/null @@ -1,23 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> - <div id="div1"></div> - <script> - is_a(document.documentElement.parentNode, Document); - is(document.documentElement.parentElement, null); - - var elem = document.createElement("p"); - is(elem.parentNode, null); - is(elem.parentElement, null); - - var child = document.createElement("p"); - elem.appendChild(child); - - is(child.parentNode, elem); - is(child.parentElement, elem); - </script> -</body> -</html> diff --git a/tests/content/test_proxy_setter.html b/tests/content/test_proxy_setter.html deleted file mode 100644 index a8bab0f3bd1..00000000000 --- a/tests/content/test_proxy_setter.html +++ /dev/null @@ -1,13 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> -<script> -is(window.document.title, ''); -window.document.title = 'foo'; -is(window.document.title, 'foo'); -</script> -</body> -</html> diff --git a/tests/content/test_textcontent.html b/tests/content/test_textcontent.html deleted file mode 100644 index 16c2c614d3e..00000000000 --- a/tests/content/test_textcontent.html +++ /dev/null @@ -1,16 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -</head> -<body> -<div>this is - text content</div> -<script> - var div = document.getElementsByTagName('div')[0]; - is(div.textContent, "this is\n text content"); - var newContent = "new text con\ntent"; - div.textContent = newContent; - is(div.textContent, newContent); -</script> -</body> -</html> diff --git a/tests/content/test_title.html b/tests/content/test_title.html deleted file mode 100644 index 117e86134df..00000000000 --- a/tests/content/test_title.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> -<head> -<title>starting title</title> -<script src="harness.js"></script> -<script> -is(document.title, "starting title"); -document.title = "new title"; -is(document.title, "new title"); -</script> -</head> -</html> diff --git a/tests/content/test_trace_null.html b/tests/content/test_trace_null.html deleted file mode 100644 index 332f158e2a1..00000000000 --- a/tests/content/test_trace_null.html +++ /dev/null @@ -1,6 +0,0 @@ -<!-- crashtest --> -<script src=harness.js></script> -<script> -new CustomEvent("foo", { detail: null }); -gc(); -</script> diff --git a/tests/content/test_union.html b/tests/content/test_union.html deleted file mode 100644 index f5fa1e933ca..00000000000 --- a/tests/content/test_union.html +++ /dev/null @@ -1,24 +0,0 @@ -<html> -<head> -<script src="harness.js"></script> -<select id="sel"></select> -<script> - var div = document.createElement('div'); - var optgroup = document.createElement('optgroup'); - var sel = document.getElementById('sel'); - - should_not_throw(function() { - var opt = document.createElement('option'); - sel.add(opt); - sel.add(optgroup); - sel.add(opt, div); - sel.add(optgroup, div); - sel.add(opt, 5); - sel.add(optgroup, 5); - }); - - should_throw(function() { sel.add(div) }); - should_not_throw(function() { sel.add(optgroup, function() {}) }); -</script> -</head> -</html> diff --git a/tests/content/test_window.html b/tests/content/test_window.html deleted file mode 100644 index 0f3cc72b274..00000000000 --- a/tests/content/test_window.html +++ /dev/null @@ -1,12 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> -<script> -is(window, window.self); -is_a(window.self, Window); -</script> -</body> -</html> diff --git a/tests/content/test_window_performance.html b/tests/content/test_window_performance.html deleted file mode 100644 index 968ca1cde3e..00000000000 --- a/tests/content/test_window_performance.html +++ /dev/null @@ -1,27 +0,0 @@ -<html> -<head> - <title></title> - <script src="harness.js"></script> -</head> -<body> -<script> - is_not(window.performance, undefined); - is_a(window.performance, Performance); - - is_not(window.performance.timing, undefined); - is_a(window.performance.timing, PerformanceTiming); - - gt(window.performance.timing.navigationStart, 0); - - var last = window.performance.now(); - gt(last, 0); - - // Check that window.performance.now() is monotonically increasing - for (var i = 0; i < 100; i++) { - var next = window.performance.now(); - gt(next, last); - last = next; - } -</script> -</body> -</html> diff --git a/tests/content/test_window_setInterval.html b/tests/content/test_window_setInterval.html deleted file mode 100644 index 6fb3ddeb6ba..00000000000 --- a/tests/content/test_window_setInterval.html +++ /dev/null @@ -1,20 +0,0 @@ -<html> - <head> - <script src="harness.js"></script> - </head> - <body> - <script> - var x = 0; - var intervalID = setInterval(function() { - x += 1; - if (x == 2) { - clearInterval(intervalID); - setTimeout(function() { - is(x, 2); - finish(); - }, 300); - } - }, 10); - </script> - </body> -</html> diff --git a/tests/content/test_windowproxy.html b/tests/content/test_windowproxy.html deleted file mode 100644 index 71c55211fd5..00000000000 --- a/tests/content/test_windowproxy.html +++ /dev/null @@ -1,23 +0,0 @@ -<html> -<head id="foo"> - <script src="harness.js"></script> -</head> -<body> -<div></div> -<script> - window.abcd = 15; - is(window.abcd, 15); - is(Object.getOwnPropertyDescriptor(window, 'abcd').value, 15); - is(window.hasOwnProperty('abcd'), true); - - is('location' in window, true); - // FIXME: https://github.com/servo/servo/issues/4593 - is(Object.hasOwnProperty('location'), false) - - // Can't set indexed properties - window[100] = "abc"; - is(window[100], undefined); - is(Object.getOwnPropertyDescriptor(window, 1000), undefined); -</script> -</body> -</html> diff --git a/tests/contenttest.rs b/tests/contenttest.rs deleted file mode 100644 index 67e24187b96..00000000000 --- a/tests/contenttest.rs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(collections)] -#![feature(exit_status)] -#![feature(path)] -#![feature(rustc_private)] -#![feature(std_misc)] -#![feature(test)] - -extern crate getopts; -extern crate test; - -use test::{AutoColor, TestOpts, run_tests_console, TestDesc, TestDescAndFn, DynTestFn, DynTestName}; -use test::ShouldPanic; -use getopts::{getopts, reqopt}; -use std::{str, env}; -use std::ffi::OsStr; -use std::fs::read_dir; -use std::process::{Command, Stdio}; -use std::thunk::Thunk; - -#[derive(Clone)] -struct Config { - source_dir: String, - filter: Option<String> -} - -fn main() { - let args = env::args(); - let config = parse_config(args.collect()); - let opts = test_options(config.clone()); - let tests = find_tests(config); - match run_tests_console(&opts, tests) { - Ok(false) => env::set_exit_status(1), // tests failed - Err(_) => env::set_exit_status(2), // I/O-related failure - _ => (), - } -} - -fn parse_config(args: Vec<String>) -> Config { - let args = args.tail(); - let opts = vec!(reqopt("s", "source-dir", "source-dir", "source-dir")); - let matches = match getopts(args, &opts) { - Ok(m) => m, - Err(f) => panic!(f.to_string()) - }; - - Config { - source_dir: matches.opt_str("source-dir").unwrap(), - filter: matches.free.first().map(|s| s.clone()) - } -} - -fn test_options(config: Config) -> TestOpts { - TestOpts { - filter: config.filter, - run_ignored: false, - run_tests: true, - run_benchmarks: false, - logfile: None, - nocapture: false, - color: AutoColor, - } -} - -fn find_tests(config: Config) -> Vec<TestDescAndFn> { - read_dir(&config.source_dir) - .ok() - .expect("Error reading directory.") - .filter_map(Result::ok) - .map(|e| e.path()) - .filter(|file| file.extension().map_or(false, |e| e == OsStr::from_str("html"))) - .map(|file| make_test(file.display().to_string())) - .collect() -} - -fn make_test(file: String) -> TestDescAndFn { - TestDescAndFn { - desc: TestDesc { - name: DynTestName(file.clone()), - ignore: false, - should_panic: ShouldPanic::No, - }, - testfn: DynTestFn(Thunk::new(move || { run_test(file) })) - } -} - -fn run_test(file: String) { - let path = env::current_dir().unwrap().join(&file); - // FIXME (#1094): not the right way to transform a path - let infile = format!("file://{}", path.display()); - let args = ["-z", "-f", &*infile]; - - let mut prc_arg = env::current_exe().unwrap(); - let prc_arg = match prc_arg.pop() { - true => prc_arg.join("servo"), - _ => panic!("could not pop directory"), - }; - let output = match Command::new(prc_arg.to_str().unwrap()) - .args(&args) - .stdin(Stdio::null()) - .stderr(Stdio::inherit()) - .output() - { - Ok(p) => p, - _ => panic!("Unable to spawn process."), - }; - - print!("{}", str::from_utf8(&output.stdout).unwrap()); - - let out = str::from_utf8(&output.stderr); - let lines: Vec<&str> = out.unwrap().split('\n').collect(); - for &line in lines.iter() { - if line.contains("TEST-UNEXPECTED-FAIL") { - panic!(line.to_string()); - } - } - - if !output.status.success() { - panic!("Servo exited with non-zero status {:?}", output.status); - } -} diff --git a/tests/ref/absolute_clipping_of_own_contents_a.html b/tests/ref/absolute_clipping_of_own_contents_a.html new file mode 100644 index 00000000000..b018d799a86 --- /dev/null +++ b/tests/ref/absolute_clipping_of_own_contents_a.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that clipping is preserved properly for nested `position: absolute` elements. --> +<style> +body, html { + margin: 0; + height: 100%; +} +#map { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 256px; + background: lightblue; + overflow: hidden; +} +#outer { + position: absolute; + left: -128px; + top: -128px; +} +#inner { + position: absolute; + background: navy; + width: 256px; + height: 256px; + left: 128px; + top: 0; +} +</style> +</head> + +<body> + <div id=map> + <div id=outer> + <div id=inner></div> + </div> + </div> +</body> +</html> diff --git a/tests/ref/absolute_clipping_of_own_contents_ref.html b/tests/ref/absolute_clipping_of_own_contents_ref.html new file mode 100644 index 00000000000..96608da13c9 --- /dev/null +++ b/tests/ref/absolute_clipping_of_own_contents_ref.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> +<!-- Tests that clipping is preserved properly for nested `position: absolute` elements. --> +<style> +body, html { + margin: 0; + height: 100%; +} +#map { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 256px; + background: lightblue; +} +#outer { + position: absolute; + left: -128px; + top: -128px; +} +#inner { + position: absolute; + background: navy; + width: 256px; + height: 256px; + left: 128px; + top: 0; +} +</style> +</head> + +<body> + <div id=map> + <div id=outer> + <div id=inner></div> + </div> + </div> +</body> +</html> diff --git a/tests/ref/basic.list b/tests/ref/basic.list index be7e36e9e89..2f17b1e9e59 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -39,6 +39,7 @@ fragment=top != ../html/acid2.html acid2_ref.html == 2dcontext/transform_a.html 2dcontext/transform_ref.html == abs_float_pref_width_a.html abs_float_pref_width_ref.html +== absolute_clipping_of_own_contents_a.html absolute_clipping_of_own_contents_ref.html == absolute_content_height_a.html absolute_content_height_ref.html == absolute_hypothetical_float_a.html absolute_hypothetical_float_ref.html == acid1_a.html acid1_b.html @@ -75,6 +76,7 @@ flaky_cpu == append_style_a.html append_style_b.html != block_image.html noteq_500x300_white.html == block_replaced_content_a.html block_replaced_content_ref.html == block_replaced_content_b.html block_replaced_content_ref.html +== blur_a.html blur_ref.html != border_black_groove.html border_black_solid.html != border_black_ridge.html border_black_groove.html != border_black_ridge.html border_black_solid.html @@ -327,6 +329,9 @@ resolution=600x800 == viewport_percentage_vmin_vmax.html viewport_percentage_vmi resolution=800x600 == viewport_percentage_vw_vh.html viewport_percentage_vw_vh_a.html resolution=600x800 == viewport_percentage_vw_vh.html viewport_percentage_vw_vh_b.html == visibility_hidden.html visibility_hidden_ref.html + +flaky_cpu == webgl-context/clearcolor.html webgl-context/clearcolor_ref.html + == whitespace_nowrap_a.html whitespace_nowrap_ref.html == whitespace_pre.html whitespace_pre_ref.html == width_nonreplaced_block_simple_a.html width_nonreplaced_block_simple_b.html diff --git a/tests/ref/blur_a.html b/tests/ref/blur_a.html new file mode 100644 index 00000000000..937b21445af --- /dev/null +++ b/tests/ref/blur_a.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<head> +<style type="text/css"> +div { + width: 200px; + height: 200px; + background: green; +} + +.ex { + position: relative; + width: 40px; height: 40px; + border-style: solid; + border-color: black; + top: 50px; left: 50px; + -webkit-filter: blur(30px); + -moz-filter: blur(30px); + filter: blur(30px); +} + +</style> +</head> +<body> + <div> + <div class="ex"></div> + </div> +</body> +</html> diff --git a/tests/ref/blur_ref.html b/tests/ref/blur_ref.html new file mode 100644 index 00000000000..1f1996f785f --- /dev/null +++ b/tests/ref/blur_ref.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<head> +<style type="text/css"> +div { + width: 200px; + height: 200px; + background: green; +} + +</style> +</head> +<body> + <div> + </div> +</body> +</html> diff --git a/tests/ref/webgl-context/clearcolor.html b/tests/ref/webgl-context/clearcolor.html new file mode 100644 index 00000000000..7d0bdeb8f2d --- /dev/null +++ b/tests/ref/webgl-context/clearcolor.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8" /> + <title>WebGL ClearColor Test</title> +</head> +<style> + +html, body { + margin: 0; +} + +</style> +<body> +<canvas id="canvas" width="640" height="480"></canvas> +<script type="text/javascript"> + +var gl = document.getElementById("canvas").getContext("webgl"); + +gl.clearColor(1.0, 0.0, 0.0, 1.0); +gl.clear(gl.COLOR_BUFFER_BIT); + +</script> +</body> +</html> diff --git a/tests/ref/webgl-context/clearcolor_ref.html b/tests/ref/webgl-context/clearcolor_ref.html new file mode 100644 index 00000000000..49cce2cc900 --- /dev/null +++ b/tests/ref/webgl-context/clearcolor_ref.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>WebGL ClearColor Test</title> +</head> +<style> + html, body { + margin: 0; + } + #canvas { + width: 640px; + height: 480px; + background-color: red; + } +</style> +<body> +<div id="canvas"></canvas> +</body> +</html> diff --git a/tests/unit/lib.rs b/tests/unit/lib.rs index f040b2e9513..05542a17840 100644 --- a/tests/unit/lib.rs +++ b/tests/unit/lib.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![feature(plugin)] -#![cfg_attr(test, feature(net, alloc))] +#![cfg_attr(test, feature(net, alloc, path, io))] #![plugin(string_cache_plugin)] diff --git a/tests/unit/net/data_loader.rs b/tests/unit/net/data_loader.rs index 482a7462bea..517788a0344 100644 --- a/tests/unit/net/data_loader.rs +++ b/tests/unit/net/data_loader.rs @@ -4,6 +4,7 @@ extern crate hyper; +use net_traits::LoadConsumer::Channel; use net_traits::LoadData; use net_traits::ProgressMsg::{Payload, Done}; use self::hyper::header::ContentType; @@ -19,7 +20,7 @@ fn assert_parse(url: &'static str, use net::data_loader::load; let (start_chan, start_port) = channel(); - load(LoadData::new(Url::parse(url).unwrap(), start_chan)); + load(LoadData::new(Url::parse(url).unwrap()), Channel(start_chan)); let response = start_port.recv().unwrap(); assert_eq!(&response.metadata.content_type, &content_type); diff --git a/tests/unit/net/image_cache_task.rs b/tests/unit/net/image_cache_task.rs index c384411fb99..6715fe8cf75 100644 --- a/tests/unit/net/image_cache_task.rs +++ b/tests/unit/net/image_cache_task.rs @@ -6,8 +6,8 @@ use net::image_cache_task::*; use net_traits::image_cache_task::ImageResponseMsg::*; use net_traits::image_cache_task::Msg::*; -use net::resource_task::start_sending; -use net_traits::{ControlMsg, Metadata, ProgressMsg, ResourceTask}; +use net::resource_task::{start_sending, ProgressSender}; +use net_traits::{ControlMsg, Metadata, ResourceTask}; use net_traits::image_cache_task::{ImageCacheTask, ImageCacheTaskClient, ImageResponseMsg, Msg}; use net_traits::ProgressMsg::{Payload, Done}; use profile::time; @@ -41,7 +41,7 @@ impl ImageCacheTaskHelper for ImageCacheTask { } trait Closure { - fn invoke(&self, _response: Sender<ProgressMsg>) { } + fn invoke(&self, _response: ProgressSender) { } } struct DoesNothing; impl Closure for DoesNothing { } @@ -50,7 +50,7 @@ struct JustSendOK { url_requested_chan: Sender<()>, } impl Closure for JustSendOK { - fn invoke(&self, response: Sender<ProgressMsg>) { + fn invoke(&self, response: ProgressSender) { self.url_requested_chan.send(()).unwrap(); response.send(Done(Ok(()))).unwrap(); } @@ -58,7 +58,7 @@ impl Closure for JustSendOK { struct SendTestImage; impl Closure for SendTestImage { - fn invoke(&self, response: Sender<ProgressMsg>) { + fn invoke(&self, response: ProgressSender) { response.send(Payload(test_image_bin())).unwrap(); response.send(Done(Ok(()))).unwrap(); } @@ -66,7 +66,7 @@ impl Closure for SendTestImage { struct SendBogusImage; impl Closure for SendBogusImage { - fn invoke(&self, response: Sender<ProgressMsg>) { + fn invoke(&self, response: ProgressSender) { response.send(Payload(vec!())).unwrap(); response.send(Done(Ok(()))).unwrap(); } @@ -74,7 +74,7 @@ impl Closure for SendBogusImage { struct SendTestImageErr; impl Closure for SendTestImageErr { - fn invoke(&self, response: Sender<ProgressMsg>) { + fn invoke(&self, response: ProgressSender) { response.send(Payload(test_image_bin())).unwrap(); response.send(Done(Err("".to_string()))).unwrap(); } @@ -84,7 +84,7 @@ struct WaitSendTestImage { wait_port: Receiver<()>, } impl Closure for WaitSendTestImage { - fn invoke(&self, response: Sender<ProgressMsg>) { + fn invoke(&self, response: ProgressSender) { // Don't send the data until after the client requests // the image self.wait_port.recv().unwrap(); @@ -97,7 +97,7 @@ struct WaitSendTestImageErr { wait_port: Receiver<()>, } impl Closure for WaitSendTestImageErr { - fn invoke(&self, response: Sender<ProgressMsg>) { + fn invoke(&self, response: ProgressSender) { // Don't send the data until after the client requests // the image self.wait_port.recv().unwrap(); @@ -110,8 +110,8 @@ fn mock_resource_task<T: Closure + Send + 'static>(on_load: Box<T>) -> ResourceT spawn_listener(move |port: Receiver<ControlMsg>| { loop { match port.recv().unwrap() { - ControlMsg::Load(response) => { - let chan = start_sending(response.consumer, Metadata::default( + ControlMsg::Load(_, consumer) => { + let chan = start_sending(consumer, Metadata::default( Url::parse("file:///fake").unwrap())); on_load.invoke(chan); } @@ -280,15 +280,15 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() { let mock_resource_task = spawn_listener(move |port: Receiver<ControlMsg>| { loop { match port.recv().unwrap() { - ControlMsg::Load(response) => { - let chan = start_sending(response.consumer, Metadata::default( + ControlMsg::Load(_, consumer) => { + let chan = start_sending(consumer, Metadata::default( Url::parse("file:///fake").unwrap())); - chan.send(Payload(test_image_bin())); - chan.send(Done(Ok(()))); - image_bin_sent_chan.send(()); + chan.send(Payload(test_image_bin())).unwrap(); + chan.send(Done(Ok(()))).unwrap(); + image_bin_sent_chan.send(()).unwrap(); } ControlMsg::Exit => { - resource_task_exited_chan.send(()); + resource_task_exited_chan.send(()).unwrap(); break } _ => {} @@ -309,7 +309,7 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() { image_cache_task.send(Prefetch(url.clone())); image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); resource_task_exited.recv().unwrap(); @@ -329,15 +329,15 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() { let mock_resource_task = spawn_listener(move |port: Receiver<ControlMsg>| { loop { match port.recv().unwrap() { - ControlMsg::Load(response) => { - let chan = start_sending(response.consumer, Metadata::default( + ControlMsg::Load(_, consumer) => { + let chan = start_sending(consumer, Metadata::default( Url::parse("file:///fake").unwrap())); - chan.send(Payload(test_image_bin())); - chan.send(Done(Err("".to_string()))); - image_bin_sent_chan.send(()); + chan.send(Payload(test_image_bin())).unwrap(); + chan.send(Done(Err("".to_string()))).unwrap(); + image_bin_sent_chan.send(()).unwrap(); } ControlMsg::Exit => { - resource_task_exited_chan.send(()); + resource_task_exited_chan.send(()).unwrap(); break } _ => {} @@ -360,7 +360,7 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() { image_cache_task.send(Decode(url.clone())); image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); resource_task_exited.recv().unwrap(); @@ -397,7 +397,7 @@ fn should_return_failed_if_image_bin_cannot_be_fetched() { } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } #[test] @@ -433,7 +433,7 @@ fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_f } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } #[test] @@ -463,7 +463,7 @@ fn should_return_failed_if_image_decode_fails() { } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } #[test] @@ -491,7 +491,7 @@ fn should_return_image_on_wait_if_image_is_already_loaded() { } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } #[test] @@ -511,7 +511,7 @@ fn should_return_image_on_wait_if_image_is_not_yet_loaded() { let (response_chan, response_port) = channel(); image_cache_task.send(Msg::WaitForImage(url, response_chan)); - wait_chan.send(()); + wait_chan.send(()).unwrap(); match response_port.recv().unwrap() { ImageResponseMsg::ImageReady(..) => (), @@ -519,7 +519,7 @@ fn should_return_image_on_wait_if_image_is_not_yet_loaded() { } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } #[test] @@ -539,7 +539,7 @@ fn should_return_image_failed_on_wait_if_image_fails_to_load() { let (response_chan, response_port) = channel(); image_cache_task.send(Msg::WaitForImage(url, response_chan)); - wait_chan.send(()); + wait_chan.send(()).unwrap(); match response_port.recv().unwrap() { ImageResponseMsg::ImageFailed => (), @@ -547,7 +547,7 @@ fn should_return_image_failed_on_wait_if_image_fails_to_load() { } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } #[test] @@ -570,5 +570,5 @@ fn sync_cache_should_wait_for_images() { } image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); + mock_resource_task.send(ControlMsg::Exit).unwrap(); } diff --git a/tests/unit/net/mime_classifier.rs b/tests/unit/net/mime_classifier.rs index eb827b6fc15..e56e76d1cb3 100644 --- a/tests/unit/net/mime_classifier.rs +++ b/tests/unit/net/mime_classifier.rs @@ -2,19 +2,30 @@ * 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 std::old_io::File; -use std::os; +use std::fs::File; +use std::io::{self, Read}; +use std::env; +use std::path::{self, PathBuf}; use net::mime_classifier::Mp4Matcher; use net::mime_classifier::MIMEClassifier; use net::mime_classifier::as_string_option; +fn read_file(path: &path::Path) -> io::Result<Vec<u8>> { + let mut file = try!(File::open(path)); + let mut buffer = Vec::new(); + + try!(file.read_to_end(&mut buffer)); + + Ok(buffer) +} + #[test] fn test_sniff_mp4_matcher() { let matcher = Mp4Matcher; - let p = Path::new("../../tests/content/parsable_mime/video/mp4/test.mp4"); - let mut file = File::open(&p); - let read_result = file.read_to_end(); + let p = PathBuf::new("../../tests/unit/net/parsable_mime/video/mp4/test.mp4"); + let read_result = read_file(&p); + match read_result { Ok(data) => { println!("Data Length {:?}",data.len()); @@ -27,42 +38,42 @@ fn test_sniff_mp4_matcher() { } #[cfg(test)] -fn test_sniff_full(filename_orig: &Path,type_string: &str,subtype_string: &str, +fn test_sniff_full(filename_orig: &path::Path,type_string: &str,subtype_string: &str, supplied_type: Option<(&'static str,&'static str)>){ - let current_working_directory = os::getcwd().unwrap(); + let current_working_directory = env::current_dir().unwrap(); println!("The current directory is {}", current_working_directory.display()); - let mut filename = Path::new("../../tests/content/parsable_mime/"); - + let mut filename = PathBuf::new("../../tests/unit/net/parsable_mime/"); filename.push(filename_orig); + let classifier = MIMEClassifier::new(); - let mut file = File::open(&filename); - let read_result = file.read_to_end(); + let read_result = read_file(&filename); + match read_result { Ok(data) => { match classifier.classify(false, false, &as_string_option(supplied_type), &data) { Some((parsed_type, parsed_subtp)) => { - if (parsed_type.as_slice() != type_string) || - (parsed_subtp.as_slice() != subtype_string) { - panic!("File {} parsed incorrectly should be {}/{}, parsed as {}/{}", - filename.as_str().unwrap(), type_string, subtype_string, + if (&parsed_type[..] != type_string) || + (&parsed_subtp[..] != subtype_string) { + panic!("File {:?} parsed incorrectly should be {}/{}, parsed as {}/{}", + filename, type_string, subtype_string, parsed_type, parsed_subtp); } } - None => panic!("No classification found for {} with supplied type {:?}", - filename.as_str().unwrap(), supplied_type), + None => panic!("No classification found for {:?} with supplied type {:?}", + filename, supplied_type), } } - Err(e) => panic!("Couldn't read from file {} with error {}", - filename.as_str().unwrap(), e), + Err(e) => panic!("Couldn't read from file {:?} with error {}", + filename, e), } } #[cfg(test)] fn test_sniff_classification(file: &str,type_string: &str,subtype_string: &str, supplied_type: Option<(&'static str,&'static str)>){ - let mut x = Path::new("./"); + let mut x = PathBuf::new("./"); x.push(type_string); x.push(subtype_string); x.push(file); @@ -170,19 +181,19 @@ fn test_sniff_vsn_ms_fontobject() { #[test] #[should_panic] fn test_sniff_true_type() { - test_sniff_full(&Path::new("unknown/true_type.ttf"), "(TrueType)", "", None); + test_sniff_full(&PathBuf::new("unknown/true_type.ttf"), "(TrueType)", "", None); } #[test] #[should_panic] fn test_sniff_open_type() { - test_sniff_full(&Path::new("unknown/open_type"), "(OpenType)", "", None); + test_sniff_full(&PathBuf::new("unknown/open_type"), "(OpenType)", "", None); } #[test] #[should_panic] fn test_sniff_true_type_collection() { - test_sniff_full(&Path::new("unknown/true_type_collection.ttc"), "(TrueType Collection)", "", None); + test_sniff_full(&PathBuf::new("unknown/true_type_collection.ttc"), "(TrueType Collection)", "", None); } #[test] @@ -424,10 +435,10 @@ fn test_sniff_utf_8_bom() { #[test] fn test_sniff_rss_feed() { - test_sniff_full(&Path::new("text/xml/feed.rss"), "application", "rss+xml", Some(("text", "html"))); + test_sniff_full(&PathBuf::new("text/xml/feed.rss"), "application", "rss+xml", Some(("text", "html"))); } #[test] fn test_sniff_atom_feed() { - test_sniff_full(&Path::new("text/xml/feed.atom"), "application", "atom+xml", Some(("text", "html"))); + test_sniff_full(&PathBuf::new("text/xml/feed.atom"), "application", "atom+xml", Some(("text", "html"))); } diff --git a/tests/content/parsable_mime/application/font-woff/test.wof b/tests/unit/net/parsable_mime/application/font-woff/test.wof index a1393ebee1d..a1393ebee1d 100755 --- a/tests/content/parsable_mime/application/font-woff/test.wof +++ b/tests/unit/net/parsable_mime/application/font-woff/test.wof diff --git a/tests/content/parsable_mime/application/ogg/small.ogg b/tests/unit/net/parsable_mime/application/ogg/small.ogg Binary files differindex 0d7f43eb795..0d7f43eb795 100644 --- a/tests/content/parsable_mime/application/ogg/small.ogg +++ b/tests/unit/net/parsable_mime/application/ogg/small.ogg diff --git a/tests/content/parsable_mime/application/pdf/test.pdf b/tests/unit/net/parsable_mime/application/pdf/test.pdf index e7c6e62775f..e7c6e62775f 100644 --- a/tests/content/parsable_mime/application/pdf/test.pdf +++ b/tests/unit/net/parsable_mime/application/pdf/test.pdf diff --git a/tests/content/parsable_mime/application/postscript/test.ps b/tests/unit/net/parsable_mime/application/postscript/test.ps index c273ffa3f0f..c273ffa3f0f 100755 --- a/tests/content/parsable_mime/application/postscript/test.ps +++ b/tests/unit/net/parsable_mime/application/postscript/test.ps diff --git a/tests/content/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject b/tests/unit/net/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject Binary files differindex 1b84f4c37c1..1b84f4c37c1 100755 --- a/tests/content/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject +++ b/tests/unit/net/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject diff --git a/tests/content/parsable_mime/application/x-gzip/test.gz b/tests/unit/net/parsable_mime/application/x-gzip/test.gz Binary files differindex 3b99b73e6f0..3b99b73e6f0 100644 --- a/tests/content/parsable_mime/application/x-gzip/test.gz +++ b/tests/unit/net/parsable_mime/application/x-gzip/test.gz diff --git a/tests/content/parsable_mime/application/x-rar-compressed/test.rar b/tests/unit/net/parsable_mime/application/x-rar-compressed/test.rar Binary files differindex 920bd4d8a8c..920bd4d8a8c 100755 --- a/tests/content/parsable_mime/application/x-rar-compressed/test.rar +++ b/tests/unit/net/parsable_mime/application/x-rar-compressed/test.rar diff --git a/tests/content/parsable_mime/application/zip/test.zip b/tests/unit/net/parsable_mime/application/zip/test.zip index 5c74c9658c6..5c74c9658c6 100755 --- a/tests/content/parsable_mime/application/zip/test.zip +++ b/tests/unit/net/parsable_mime/application/zip/test.zip diff --git a/tests/content/parsable_mime/audio/aiff/test.aif b/tests/unit/net/parsable_mime/audio/aiff/test.aif Binary files differindex ad2e35df40b..ad2e35df40b 100644 --- a/tests/content/parsable_mime/audio/aiff/test.aif +++ b/tests/unit/net/parsable_mime/audio/aiff/test.aif diff --git a/tests/content/parsable_mime/audio/basic/test.au b/tests/unit/net/parsable_mime/audio/basic/test.au Binary files differindex d4e53deb74a..d4e53deb74a 100644 --- a/tests/content/parsable_mime/audio/basic/test.au +++ b/tests/unit/net/parsable_mime/audio/basic/test.au diff --git a/tests/content/parsable_mime/audio/midi/test.mid b/tests/unit/net/parsable_mime/audio/midi/test.mid Binary files differindex a52838c62bc..a52838c62bc 100644 --- a/tests/content/parsable_mime/audio/midi/test.mid +++ b/tests/unit/net/parsable_mime/audio/midi/test.mid diff --git a/tests/content/parsable_mime/audio/mpeg/test.mp3 b/tests/unit/net/parsable_mime/audio/mpeg/test.mp3 Binary files differindex 50786790311..50786790311 100644 --- a/tests/content/parsable_mime/audio/mpeg/test.mp3 +++ b/tests/unit/net/parsable_mime/audio/mpeg/test.mp3 diff --git a/tests/content/parsable_mime/audio/wave/test.wav b/tests/unit/net/parsable_mime/audio/wave/test.wav Binary files differindex f96276c063c..f96276c063c 100644 --- a/tests/content/parsable_mime/audio/wave/test.wav +++ b/tests/unit/net/parsable_mime/audio/wave/test.wav diff --git a/tests/content/parsable_mime/image/bmp/test.bmp b/tests/unit/net/parsable_mime/image/bmp/test.bmp Binary files differindex 8a1b10bae5e..8a1b10bae5e 100644 --- a/tests/content/parsable_mime/image/bmp/test.bmp +++ b/tests/unit/net/parsable_mime/image/bmp/test.bmp diff --git a/tests/content/parsable_mime/image/gif/test87a b/tests/unit/net/parsable_mime/image/gif/test87a Binary files differindex 8d49c776420..8d49c776420 100644 --- a/tests/content/parsable_mime/image/gif/test87a +++ b/tests/unit/net/parsable_mime/image/gif/test87a diff --git a/tests/content/parsable_mime/image/gif/test89a.gif b/tests/unit/net/parsable_mime/image/gif/test89a.gif Binary files differindex 0e2995e0821..0e2995e0821 100644 --- a/tests/content/parsable_mime/image/gif/test89a.gif +++ b/tests/unit/net/parsable_mime/image/gif/test89a.gif diff --git a/tests/content/parsable_mime/image/jpeg/test.jpg b/tests/unit/net/parsable_mime/image/jpeg/test.jpg Binary files differindex 7f758f65d13..7f758f65d13 100644 --- a/tests/content/parsable_mime/image/jpeg/test.jpg +++ b/tests/unit/net/parsable_mime/image/jpeg/test.jpg diff --git a/tests/content/parsable_mime/image/png/test.png b/tests/unit/net/parsable_mime/image/png/test.png Binary files differindex cc81374d4f5..cc81374d4f5 100644 --- a/tests/content/parsable_mime/image/png/test.png +++ b/tests/unit/net/parsable_mime/image/png/test.png diff --git a/tests/content/parsable_mime/image/webp/test.webp b/tests/unit/net/parsable_mime/image/webp/test.webp Binary files differindex 5a907eb4ce2..5a907eb4ce2 100755 --- a/tests/content/parsable_mime/image/webp/test.webp +++ b/tests/unit/net/parsable_mime/image/webp/test.webp diff --git a/tests/content/parsable_mime/image/x-icon/test.ico b/tests/unit/net/parsable_mime/image/x-icon/test.ico Binary files differindex a2d0ee49098..a2d0ee49098 100644 --- a/tests/content/parsable_mime/image/x-icon/test.ico +++ b/tests/unit/net/parsable_mime/image/x-icon/test.ico diff --git a/tests/content/parsable_mime/image/x-icon/test_cursor.ico b/tests/unit/net/parsable_mime/image/x-icon/test_cursor.ico Binary files differindex 6029d6684d5..6029d6684d5 100644 --- a/tests/content/parsable_mime/image/x-icon/test_cursor.ico +++ b/tests/unit/net/parsable_mime/image/x-icon/test_cursor.ico diff --git a/tests/content/parsable_mime/text/html/text_html_a_20.html b/tests/unit/net/parsable_mime/text/html/text_html_a_20.html index 1b9619279a7..1b9619279a7 100644 --- a/tests/content/parsable_mime/text/html/text_html_a_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_a_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_a_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_a_20_u.html index 887a1280650..887a1280650 100644 --- a/tests/content/parsable_mime/text/html/text_html_a_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_a_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_a_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_a_3e.html index 610cd08fea4..610cd08fea4 100644 --- a/tests/content/parsable_mime/text/html/text_html_a_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_a_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_a_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_a_3e_u.html index 48528fdf341..48528fdf341 100644 --- a/tests/content/parsable_mime/text/html/text_html_a_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_a_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_b_20.html b/tests/unit/net/parsable_mime/text/html/text_html_b_20.html index 5977d2eeaab..5977d2eeaab 100644 --- a/tests/content/parsable_mime/text/html/text_html_b_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_b_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_b_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_b_20_u.html index a8a963b95f0..a8a963b95f0 100644 --- a/tests/content/parsable_mime/text/html/text_html_b_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_b_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_b_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_b_3e.html index dc79cd5d568..dc79cd5d568 100644 --- a/tests/content/parsable_mime/text/html/text_html_b_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_b_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_b_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_b_3e_u.html index 0d72d281aec..0d72d281aec 100644 --- a/tests/content/parsable_mime/text/html/text_html_b_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_b_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_body_20.html b/tests/unit/net/parsable_mime/text/html/text_html_body_20.html index c72b1ad3bec..c72b1ad3bec 100644 --- a/tests/content/parsable_mime/text/html/text_html_body_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_body_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_body_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_body_20_u.html index 1d76ebb0f47..1d76ebb0f47 100644 --- a/tests/content/parsable_mime/text/html/text_html_body_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_body_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_body_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_body_3e.html index 4a66f59ef95..4a66f59ef95 100644 --- a/tests/content/parsable_mime/text/html/text_html_body_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_body_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_body_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_body_3e_u.html index b431695f3ab..b431695f3ab 100644 --- a/tests/content/parsable_mime/text/html/text_html_body_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_body_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_br_20.html b/tests/unit/net/parsable_mime/text/html/text_html_br_20.html index d04df680012..d04df680012 100644 --- a/tests/content/parsable_mime/text/html/text_html_br_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_br_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_br_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_br_20_u.html index 1c0f0ce13ba..1c0f0ce13ba 100644 --- a/tests/content/parsable_mime/text/html/text_html_br_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_br_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_br_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_br_3e.html index 1d40ef06566..1d40ef06566 100644 --- a/tests/content/parsable_mime/text/html/text_html_br_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_br_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_br_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_br_3e_u.html index c4eae116f03..c4eae116f03 100644 --- a/tests/content/parsable_mime/text/html/text_html_br_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_br_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_comment_20.html b/tests/unit/net/parsable_mime/text/html/text_html_comment_20.html index e9612efc73c..e9612efc73c 100644 --- a/tests/content/parsable_mime/text/html/text_html_comment_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_comment_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_comment_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_comment_20_u.html index e9612efc73c..e9612efc73c 100644 --- a/tests/content/parsable_mime/text/html/text_html_comment_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_comment_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_comment_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_comment_3e.html index 44a94ca5a7a..44a94ca5a7a 100644 --- a/tests/content/parsable_mime/text/html/text_html_comment_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_comment_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_comment_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_comment_3e_u.html index 44a94ca5a7a..44a94ca5a7a 100644 --- a/tests/content/parsable_mime/text/html/text_html_comment_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_comment_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_div_20.html b/tests/unit/net/parsable_mime/text/html/text_html_div_20.html index 2ed34363b2f..2ed34363b2f 100644 --- a/tests/content/parsable_mime/text/html/text_html_div_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_div_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_div_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_div_20_u.html index b98886efd83..b98886efd83 100644 --- a/tests/content/parsable_mime/text/html/text_html_div_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_div_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_div_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_div_3e.html index ccf4ca8d70a..ccf4ca8d70a 100644 --- a/tests/content/parsable_mime/text/html/text_html_div_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_div_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_div_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_div_3e_u.html index c117f0f4cdd..c117f0f4cdd 100644 --- a/tests/content/parsable_mime/text/html/text_html_div_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_div_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_doctype_20.html b/tests/unit/net/parsable_mime/text/html/text_html_doctype_20.html index dbeb5a41c2a..dbeb5a41c2a 100644 --- a/tests/content/parsable_mime/text/html/text_html_doctype_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_doctype_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_doctype_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_doctype_20_u.html index acede44dffb..acede44dffb 100644 --- a/tests/content/parsable_mime/text/html/text_html_doctype_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_doctype_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_doctype_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_doctype_3e.html index 6a22ea8b978..6a22ea8b978 100644 --- a/tests/content/parsable_mime/text/html/text_html_doctype_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_doctype_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_doctype_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_doctype_3e_u.html index 8b16e40458e..8b16e40458e 100644 --- a/tests/content/parsable_mime/text/html/text_html_doctype_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_doctype_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_font_20.html b/tests/unit/net/parsable_mime/text/html/text_html_font_20.html index a18fa850617..a18fa850617 100644 --- a/tests/content/parsable_mime/text/html/text_html_font_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_font_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_font_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_font_20_u.html index 6a31d2a8aba..6a31d2a8aba 100644 --- a/tests/content/parsable_mime/text/html/text_html_font_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_font_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_font_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_font_3e.html index 3605840fc5a..3605840fc5a 100644 --- a/tests/content/parsable_mime/text/html/text_html_font_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_font_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_font_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_font_3e_u.html index 1181517947b..1181517947b 100644 --- a/tests/content/parsable_mime/text/html/text_html_font_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_font_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_h1_20.html b/tests/unit/net/parsable_mime/text/html/text_html_h1_20.html index 3ed0eb125ff..3ed0eb125ff 100644 --- a/tests/content/parsable_mime/text/html/text_html_h1_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_h1_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_h1_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_h1_20_u.html index f517b61487e..f517b61487e 100644 --- a/tests/content/parsable_mime/text/html/text_html_h1_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_h1_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_h1_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_h1_3e.html index af0bf8c56b9..af0bf8c56b9 100644 --- a/tests/content/parsable_mime/text/html/text_html_h1_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_h1_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_h1_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_h1_3e_u.html index bae85229fcf..bae85229fcf 100644 --- a/tests/content/parsable_mime/text/html/text_html_h1_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_h1_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_head_20.html b/tests/unit/net/parsable_mime/text/html/text_html_head_20.html index eb322c946e0..eb322c946e0 100644 --- a/tests/content/parsable_mime/text/html/text_html_head_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_head_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_head_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_head_20_u.html index 899655a5a2c..899655a5a2c 100644 --- a/tests/content/parsable_mime/text/html/text_html_head_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_head_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_head_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_head_3e.html index 058c7dce4a9..058c7dce4a9 100644 --- a/tests/content/parsable_mime/text/html/text_html_head_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_head_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_head_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_head_3e_u.html index 8a33d623daa..8a33d623daa 100644 --- a/tests/content/parsable_mime/text/html/text_html_head_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_head_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_iframe_20.html b/tests/unit/net/parsable_mime/text/html/text_html_iframe_20.html index e632915590a..e632915590a 100644 --- a/tests/content/parsable_mime/text/html/text_html_iframe_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_iframe_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_iframe_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_iframe_20_u.html index 527a06e415c..527a06e415c 100644 --- a/tests/content/parsable_mime/text/html/text_html_iframe_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_iframe_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_iframe_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_iframe_3e.html index 9db0efd47d4..9db0efd47d4 100644 --- a/tests/content/parsable_mime/text/html/text_html_iframe_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_iframe_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_iframe_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_iframe_3e_u.html index e3512c8a5c2..e3512c8a5c2 100644 --- a/tests/content/parsable_mime/text/html/text_html_iframe_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_iframe_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_p_20.html b/tests/unit/net/parsable_mime/text/html/text_html_p_20.html index a099441be2b..a099441be2b 100644 --- a/tests/content/parsable_mime/text/html/text_html_p_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_p_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_p_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_p_20_u.html index ff4befbde7b..ff4befbde7b 100644 --- a/tests/content/parsable_mime/text/html/text_html_p_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_p_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_p_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_p_3e.html index 98db18913d0..98db18913d0 100644 --- a/tests/content/parsable_mime/text/html/text_html_p_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_p_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_p_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_p_3e_u.html index 9d99a59ed08..9d99a59ed08 100644 --- a/tests/content/parsable_mime/text/html/text_html_p_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_p_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_page_20.html b/tests/unit/net/parsable_mime/text/html/text_html_page_20.html index bb1c4572b25..bb1c4572b25 100644 --- a/tests/content/parsable_mime/text/html/text_html_page_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_page_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_page_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_page_20_u.html index b3300d9f4e4..b3300d9f4e4 100644 --- a/tests/content/parsable_mime/text/html/text_html_page_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_page_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_page_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_page_3e.html index e6a49c51924..e6a49c51924 100644 --- a/tests/content/parsable_mime/text/html/text_html_page_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_page_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_page_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_page_3e_u.html index 2b8ee203d25..2b8ee203d25 100644 --- a/tests/content/parsable_mime/text/html/text_html_page_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_page_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_script_20.html b/tests/unit/net/parsable_mime/text/html/text_html_script_20.html index 620c629266c..620c629266c 100644 --- a/tests/content/parsable_mime/text/html/text_html_script_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_script_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_script_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_script_20_u.html index bd2c58e676c..bd2c58e676c 100644 --- a/tests/content/parsable_mime/text/html/text_html_script_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_script_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_script_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_script_3e.html index d59535f70cd..d59535f70cd 100644 --- a/tests/content/parsable_mime/text/html/text_html_script_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_script_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_script_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_script_3e_u.html index 625c13820f4..625c13820f4 100644 --- a/tests/content/parsable_mime/text/html/text_html_script_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_script_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_style_20.html b/tests/unit/net/parsable_mime/text/html/text_html_style_20.html index 57bc2a1ecd7..57bc2a1ecd7 100644 --- a/tests/content/parsable_mime/text/html/text_html_style_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_style_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_style_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_style_20_u.html index 8163eca3c60..8163eca3c60 100644 --- a/tests/content/parsable_mime/text/html/text_html_style_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_style_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_style_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_style_3e.html index 229d5f951bd..229d5f951bd 100644 --- a/tests/content/parsable_mime/text/html/text_html_style_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_style_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_style_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_style_3e_u.html index 12d686e4953..12d686e4953 100644 --- a/tests/content/parsable_mime/text/html/text_html_style_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_style_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_table_20.html b/tests/unit/net/parsable_mime/text/html/text_html_table_20.html index 27cccc6acd6..27cccc6acd6 100644 --- a/tests/content/parsable_mime/text/html/text_html_table_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_table_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_table_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_table_20_u.html index 556b46e7fc4..556b46e7fc4 100644 --- a/tests/content/parsable_mime/text/html/text_html_table_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_table_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_table_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_table_3e.html index 351ee543af8..351ee543af8 100644 --- a/tests/content/parsable_mime/text/html/text_html_table_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_table_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_table_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_table_3e_u.html index 6259870bfcf..6259870bfcf 100644 --- a/tests/content/parsable_mime/text/html/text_html_table_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_table_3e_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_title_20.html b/tests/unit/net/parsable_mime/text/html/text_html_title_20.html index f7d151658d9..f7d151658d9 100644 --- a/tests/content/parsable_mime/text/html/text_html_title_20.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_title_20.html diff --git a/tests/content/parsable_mime/text/html/text_html_title_20_u.html b/tests/unit/net/parsable_mime/text/html/text_html_title_20_u.html index 03a072d8ac0..03a072d8ac0 100644 --- a/tests/content/parsable_mime/text/html/text_html_title_20_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_title_20_u.html diff --git a/tests/content/parsable_mime/text/html/text_html_title_3e.html b/tests/unit/net/parsable_mime/text/html/text_html_title_3e.html index fedf57b9e4f..fedf57b9e4f 100644 --- a/tests/content/parsable_mime/text/html/text_html_title_3e.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_title_3e.html diff --git a/tests/content/parsable_mime/text/html/text_html_title_3e_u.html b/tests/unit/net/parsable_mime/text/html/text_html_title_3e_u.html index 5fbf8a75c47..5fbf8a75c47 100644 --- a/tests/content/parsable_mime/text/html/text_html_title_3e_u.html +++ b/tests/unit/net/parsable_mime/text/html/text_html_title_3e_u.html diff --git a/tests/content/parsable_mime/text/plain/utf16bebom.txt b/tests/unit/net/parsable_mime/text/plain/utf16bebom.txt Binary files differindex 9fb50d49fb8..9fb50d49fb8 100644 --- a/tests/content/parsable_mime/text/plain/utf16bebom.txt +++ b/tests/unit/net/parsable_mime/text/plain/utf16bebom.txt diff --git a/tests/content/parsable_mime/text/plain/utf16lebom.txt b/tests/unit/net/parsable_mime/text/plain/utf16lebom.txt Binary files differindex d79d81725ec..d79d81725ec 100644 --- a/tests/content/parsable_mime/text/plain/utf16lebom.txt +++ b/tests/unit/net/parsable_mime/text/plain/utf16lebom.txt diff --git a/tests/content/parsable_mime/text/plain/utf8bom.txt b/tests/unit/net/parsable_mime/text/plain/utf8bom.txt index 56ad8a265ef..56ad8a265ef 100644 --- a/tests/content/parsable_mime/text/plain/utf8bom.txt +++ b/tests/unit/net/parsable_mime/text/plain/utf8bom.txt diff --git a/tests/content/parsable_mime/text/xml/feed.atom b/tests/unit/net/parsable_mime/text/xml/feed.atom index 893c3f27a8e..893c3f27a8e 100755 --- a/tests/content/parsable_mime/text/xml/feed.atom +++ b/tests/unit/net/parsable_mime/text/xml/feed.atom diff --git a/tests/content/parsable_mime/text/xml/feed.rss b/tests/unit/net/parsable_mime/text/xml/feed.rss index 9dc94d32b51..9dc94d32b51 100644 --- a/tests/content/parsable_mime/text/xml/feed.rss +++ b/tests/unit/net/parsable_mime/text/xml/feed.rss diff --git a/tests/content/parsable_mime/text/xml/test.xml b/tests/unit/net/parsable_mime/text/xml/test.xml index 8fe8c0e91cf..8fe8c0e91cf 100644 --- a/tests/content/parsable_mime/text/xml/test.xml +++ b/tests/unit/net/parsable_mime/text/xml/test.xml diff --git a/tests/content/parsable_mime/unknown/open_type b/tests/unit/net/parsable_mime/unknown/open_type index 9117b12600f..9117b12600f 100644 --- a/tests/content/parsable_mime/unknown/open_type +++ b/tests/unit/net/parsable_mime/unknown/open_type diff --git a/tests/content/parsable_mime/unknown/true_type.ttf b/tests/unit/net/parsable_mime/unknown/true_type.ttf Binary files differindex c0142fea093..c0142fea093 100644 --- a/tests/content/parsable_mime/unknown/true_type.ttf +++ b/tests/unit/net/parsable_mime/unknown/true_type.ttf diff --git a/tests/content/parsable_mime/unknown/true_type_collection.ttc b/tests/unit/net/parsable_mime/unknown/true_type_collection.ttc index 42d3cef1e6d..42d3cef1e6d 100644 --- a/tests/content/parsable_mime/unknown/true_type_collection.ttc +++ b/tests/unit/net/parsable_mime/unknown/true_type_collection.ttc diff --git a/tests/content/parsable_mime/video/avi/test.avi b/tests/unit/net/parsable_mime/video/avi/test.avi Binary files differindex f6cd837a924..f6cd837a924 100644 --- a/tests/content/parsable_mime/video/avi/test.avi +++ b/tests/unit/net/parsable_mime/video/avi/test.avi diff --git a/tests/content/parsable_mime/video/mp4/test.mp4 b/tests/unit/net/parsable_mime/video/mp4/test.mp4 Binary files differindex 1fc478842f5..1fc478842f5 100644 --- a/tests/content/parsable_mime/video/mp4/test.mp4 +++ b/tests/unit/net/parsable_mime/video/mp4/test.mp4 diff --git a/tests/content/parsable_mime/video/webm/test.webm b/tests/unit/net/parsable_mime/video/webm/test.webm Binary files differindex da946da5290..da946da5290 100644 --- a/tests/content/parsable_mime/video/webm/test.webm +++ b/tests/unit/net/parsable_mime/video/webm/test.webm diff --git a/tests/unit/net/resource_task.rs b/tests/unit/net/resource_task.rs index da79322a2ff..d9ef7cde4d3 100644 --- a/tests/unit/net/resource_task.rs +++ b/tests/unit/net/resource_task.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use net::resource_task::{new_resource_task, parse_hostsfile, replace_hosts}; -use net_traits::{ControlMsg, LoadData}; +use net_traits::{ControlMsg, LoadData, LoadConsumer}; use net_traits::ProgressMsg; use std::borrow::ToOwned; use std::boxed; @@ -23,7 +23,7 @@ fn test_bad_scheme() { let resource_task = new_resource_task(None); let (start_chan, start) = channel(); let url = Url::parse("bogus://whatever").unwrap(); - resource_task.send(ControlMsg::Load(LoadData::new(url, start_chan))).unwrap(); + resource_task.send(ControlMsg::Load(LoadData::new(url), LoadConsumer::Channel(start_chan))).unwrap(); let response = start.recv().unwrap(); match response.progress_port.recv().unwrap() { ProgressMsg::Done(result) => { assert!(result.is_err()) } @@ -173,7 +173,7 @@ fn test_replace_hosts() { let resource_task = new_resource_task(None); let (start_chan, _) = channel(); let url = Url::parse(&format!("http://foo.bar.com:{}", port)).unwrap(); - resource_task.send(ControlMsg::Load(replace_hosts(LoadData::new(url, start_chan), host_table))).unwrap(); + resource_task.send(ControlMsg::Load(replace_hosts(LoadData::new(url), host_table), LoadConsumer::Channel(start_chan))).unwrap(); match listener.accept() { Ok(..) => assert!(true, "received request"), diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html.ini deleted file mode 100644 index 90e93b43b2d..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.drawImage.path.html] - type: testharness - [Canvas test: 2d.drawImage.path] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html.ini b/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html.ini deleted file mode 100644 index 615202eb6b5..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.clearRect.path.html] - type: testharness - [clearRect does not affect the current path] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html.ini b/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html.ini deleted file mode 100644 index b3bd1685ad2..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.fillRect.path.html] - type: testharness - [fillRect does not affect the current path] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html.ini b/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html.ini deleted file mode 100644 index 3fb4bbb762f..00000000000 --- a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.strokeRect.path.html] - type: testharness - [strokeRect does not affect the current path] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html.ini b/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html.ini deleted file mode 100644 index 4e811b1293f..00000000000 --- a/tests/wpt/metadata/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.gradient.interpolate.zerosize.fill.html] - type: testharness - [Canvas test: 2d.gradient.interpolate.zerosize.fill] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.width.transformed.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.width.transformed.html.ini deleted file mode 100644 index 7f6d331fab2..00000000000 --- a/tests/wpt/metadata/2dcontext/line-styles/2d.line.width.transformed.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.line.width.transformed.html] - type: testharness - [Line stroke widths are affected by scale transformations] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/line-styles/canvas_linestyles_linecap_001.htm.ini b/tests/wpt/metadata/2dcontext/line-styles/canvas_linestyles_linecap_001.htm.ini index e880cc0b0aa..5bdb0f12a0b 100644 --- a/tests/wpt/metadata/2dcontext/line-styles/canvas_linestyles_linecap_001.htm.ini +++ b/tests/wpt/metadata/2dcontext/line-styles/canvas_linestyles_linecap_001.htm.ini @@ -2,4 +2,4 @@ type: reftest reftype: == refurl: /2dcontext/line-styles/canvas_linestyles_linecap_001-ref.htm - expected: FAIL + disabled: intermittently passing #5714 diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html.ini deleted file mode 100644 index 170abb8500e..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.arcTo.shape.curve1.html] - type: testharness - [arcTo() curves in the right kind of shape] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini deleted file mode 100644 index 3ceefeb7d1a..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.arcTo.shape.curve2.html] - type: testharness - [arcTo() curves in the right kind of shape] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.beginPath.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.beginPath.html.ini deleted file mode 100644 index 9dba6a39c78..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.beginPath.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.beginPath.html] - type: testharness - [Canvas test: 2d.path.beginPath] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.fill.overlap.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.fill.overlap.html.ini deleted file mode 100644 index ed2f2f9b29a..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.fill.overlap.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.fill.overlap.html] - type: testharness - [Canvas test: 2d.path.fill.overlap] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.basic.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.basic.html.ini deleted file mode 100644 index 09fcdf36b81..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.basic.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.moveTo.basic.html] - type: testharness - [Canvas test: 2d.path.moveTo.basic] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.basic.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.basic.html.ini deleted file mode 100644 index 0abc294400a..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.basic.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.basic.html] - type: testharness - [Canvas test: 2d.path.rect.basic] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.closed.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.closed.html.ini deleted file mode 100644 index 998dd532bc5..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.closed.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.closed.html] - type: testharness - [Canvas test: 2d.path.rect.closed] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.end.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.end.1.html.ini deleted file mode 100644 index 24ffbf09995..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.end.1.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.end.1.html] - type: testharness - [Canvas test: 2d.path.rect.end.1] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.end.2.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.end.2.html.ini deleted file mode 100644 index c1fc1a7218a..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.end.2.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.end.2.html] - type: testharness - [Canvas test: 2d.path.rect.end.2] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.negative.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.negative.html.ini deleted file mode 100644 index 9abbc1efdae..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.negative.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.negative.html] - type: testharness - [Canvas test: 2d.path.rect.negative] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.newsubpath.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.newsubpath.html.ini deleted file mode 100644 index a686aeaa694..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.newsubpath.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.newsubpath.html] - type: testharness - [Canvas test: 2d.path.rect.newsubpath] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.nonfinite.html.ini deleted file mode 100644 index 3e9d98ef623..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.nonfinite.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.nonfinite.html] - type: testharness - [rect() with Infinity/NaN is ignored] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.selfintersect.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.selfintersect.html.ini deleted file mode 100644 index ba5026a5284..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.selfintersect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.selfintersect.html] - type: testharness - [Canvas test: 2d.path.rect.selfintersect] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.winding.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.winding.html.ini deleted file mode 100644 index 9d513c9678f..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.winding.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.winding.html] - type: testharness - [Canvas test: 2d.path.rect.winding] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.1.html.ini deleted file mode 100644 index 4d0ceb9e0a0..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.1.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.zero.1.html] - type: testharness - [Canvas test: 2d.path.rect.zero.1] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.2.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.2.html.ini deleted file mode 100644 index 62cf2bed704..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.2.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.zero.2.html] - type: testharness - [Canvas test: 2d.path.rect.zero.2] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.3.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.3.html.ini deleted file mode 100644 index ba8f7d7aee6..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.3.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.zero.3.html] - type: testharness - [Canvas test: 2d.path.rect.zero.3] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.4.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.4.html.ini deleted file mode 100644 index 510e9f6960e..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.4.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.zero.4.html] - type: testharness - [Canvas test: 2d.path.rect.zero.4] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.5.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.5.html.ini deleted file mode 100644 index b35c28f56d9..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.5.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.zero.5.html] - type: testharness - [Canvas test: 2d.path.rect.zero.5] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.6.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.6.html.ini deleted file mode 100644 index 89e66cb7e8e..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.rect.zero.6.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.rect.zero.6.html] - type: testharness - [Canvas test: 2d.path.rect.zero.6] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.rect.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.rect.html.ini deleted file mode 100644 index 129a2d6d000..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.rect.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.stroke.prune.rect.html] - type: testharness - [Zero-length line segments from rect and strokeRect are removed before stroking] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.transformation.multiple.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.transformation.multiple.html.ini deleted file mode 100644 index b59844f2c8c..00000000000 --- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.transformation.multiple.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.path.transformation.multiple.html] - type: testharness - [Transformations are applied while building paths, not when drawing] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.path.html.ini b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.path.html.ini deleted file mode 100644 index ac486347a73..00000000000 --- a/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.path.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.imageData.put.path.html] - type: testharness - [putImageData() does not affect the current path] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html.ini deleted file mode 100644 index 16cf3284387..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.bitmap.html] - type: testharness - [save()/restore() does not affect the current bitmap] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html.ini deleted file mode 100644 index e99c74d2806..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.fillStyle.html] - type: testharness - [save()/restore() works for fillStyle] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html.ini deleted file mode 100644 index d4676a347c0..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.globalAlpha.html] - type: testharness - [save()/restore() works for globalAlpha] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html.ini deleted file mode 100644 index 11ee72efd6e..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.lineCap.html] - type: testharness - [save()/restore() works for lineCap] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html.ini deleted file mode 100644 index cba7c1653fe..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.lineJoin.html] - type: testharness - [save()/restore() works for lineJoin] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html.ini deleted file mode 100644 index 8be9e715f82..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.lineWidth.html] - type: testharness - [save()/restore() works for lineWidth] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html.ini deleted file mode 100644 index c60e9b276a7..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.miterLimit.html] - type: testharness - [save()/restore() works for miterLimit] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.path.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.path.html.ini deleted file mode 100644 index 7050240d9bf..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.path.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.path.html] - type: testharness - [save()/restore() does not affect the current path] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.stack.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.stack.html.ini deleted file mode 100644 index 7a1db072d37..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.stack.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.stack.html] - type: testharness - [save()/restore() can be nested as a stack] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html.ini deleted file mode 100644 index a3658368a1c..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.stackdepth.html] - type: testharness - [save()/restore() stack depth is not unreasonably limited] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html.ini deleted file mode 100644 index 767f020c0a1..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.strokeStyle.html] - type: testharness - [save()/restore() works for strokeStyle] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html.ini deleted file mode 100644 index 57e9fdc6068..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.transformation.html] - type: testharness - [save()/restore() affects the current transformation matrix] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html.ini deleted file mode 100644 index 80a4e6d4819..00000000000 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.state.saverestore.underflow.html] - type: testharness - [restore() with an empty stack has no effect] - expected: FAIL - diff --git a/tests/wpt/metadata/2dcontext/the-canvas-state/canvas_state_restore_001.htm.ini b/tests/wpt/metadata/2dcontext/the-canvas-state/canvas_state_restore_001.htm.ini index 539034fbef9..4924ed36848 100644 --- a/tests/wpt/metadata/2dcontext/the-canvas-state/canvas_state_restore_001.htm.ini +++ b/tests/wpt/metadata/2dcontext/the-canvas-state/canvas_state_restore_001.htm.ini @@ -3,3 +3,4 @@ reftype: == refurl: /2dcontext/the-canvas-state/canvas_state_restore_001-ref.htm expected: FAIL + disabled: intermittent pass #5764 diff --git a/tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.negative.html.ini b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.negative.html.ini deleted file mode 100644 index 70876efb171..00000000000 --- a/tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.negative.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[2d.transformation.scale.negative.html] - type: testharness - [scale() with negative scale factors works] - expected: FAIL - diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 5584274dfb0..59233ae40ce 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -710,6 +710,14 @@ "url": "/html/semantics/forms/the-input-element/file-manual.html" }, { + "path": "html/semantics/forms/the-textarea-element/textarea-select-event-manual.html", + "url": "/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html" + }, + { + "path": "html/semantics/forms/the-textarea-element/textarea-select-manual.html", + "url": "/html/semantics/forms/the-textarea-element/textarea-select-manual.html" + }, + { "path": "html/semantics/grouping-content/the-li-element/grouping-li-novalue-manual.html", "url": "/html/semantics/grouping-content/the-li-element/grouping-li-novalue-manual.html" }, @@ -8408,10 +8416,6 @@ "url": "/IndexedDB/idbdatabase_createObjectStore7.htm" }, { - "path": "IndexedDB/idbdatabase_createObjectStore8-parameters.htm", - "url": "/IndexedDB/idbdatabase_createObjectStore8-parameters.htm" - }, - { "path": "IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm", "url": "/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm" }, @@ -9624,6 +9628,14 @@ "url": "/XMLHttpRequest/send-timeout-events.htm" }, { + "path": "XMLHttpRequest/send-usp.html", + "url": "/XMLHttpRequest/send-usp.html" + }, + { + "path": "XMLHttpRequest/send-usp.worker.js", + "url": "/XMLHttpRequest/send-usp.worker" + }, + { "path": "XMLHttpRequest/setrequestheader-after-send.htm", "url": "/XMLHttpRequest/setrequestheader-after-send.htm" }, @@ -9696,58 +9708,6 @@ "url": "/XMLHttpRequest/xmlhttprequest-network-error.htm" }, { - "path": "XMLHttpRequest/xmlhttprequest-timeout-aborted.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-aborted.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-overrides.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-overrides.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-simple.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-simple.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-synconmain.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-twice.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-twice.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html" - }, - { - "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html", - "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html" - }, - { "path": "XMLHttpRequest/xmlhttprequest-unsent.htm", "url": "/XMLHttpRequest/xmlhttprequest-unsent.htm" }, @@ -16140,6 +16100,74 @@ "url": "/selectors/attribute-selectors/attribute-case/syntax.html" }, { + "path": "service-workers/cache-storage/common.https.html", + "url": "/service-workers/cache-storage/common.https.html" + }, + { + "path": "service-workers/cache-storage/serviceworker/cache-add.https.html", + "url": "/service-workers/cache-storage/serviceworker/cache-add.https.html" + }, + { + "path": "service-workers/cache-storage/serviceworker/cache-delete.https.html", + "url": "/service-workers/cache-storage/serviceworker/cache-delete.https.html" + }, + { + "path": "service-workers/cache-storage/serviceworker/cache-storage-keys.https.html", + "url": "/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html" + }, + { + "path": "service-workers/cache-storage/serviceworker/cache-storage-match.https.html", + "url": "/service-workers/cache-storage/serviceworker/cache-storage-match.https.html" + }, + { + "path": "service-workers/cache-storage/serviceworker/cache-storage.https.html", + "url": "/service-workers/cache-storage/serviceworker/cache-storage.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-add.https.html", + "url": "/service-workers/cache-storage/window/cache-add.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-delete.https.html", + "url": "/service-workers/cache-storage/window/cache-delete.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-storage-keys.https.html", + "url": "/service-workers/cache-storage/window/cache-storage-keys.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-storage-match.https.html", + "url": "/service-workers/cache-storage/window/cache-storage-match.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-storage.https.html", + "url": "/service-workers/cache-storage/window/cache-storage.https.html" + }, + { + "path": "service-workers/cache-storage/window/sandboxed-iframes.https.html", + "url": "/service-workers/cache-storage/window/sandboxed-iframes.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-add.https.html", + "url": "/service-workers/cache-storage/worker/cache-add.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-delete.https.html", + "url": "/service-workers/cache-storage/worker/cache-delete.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-storage-keys.https.html", + "url": "/service-workers/cache-storage/worker/cache-storage-keys.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-storage-match.https.html", + "url": "/service-workers/cache-storage/worker/cache-storage-match.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-storage.https.html", + "url": "/service-workers/cache-storage/worker/cache-storage.https.html" + }, + { "path": "shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html", "url": "/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html" }, @@ -18785,6 +18813,11 @@ "url": "/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm" }, { + "path": "IndexedDB/idbdatabase_createObjectStore8-parameters.htm", + "timeout": "long", + "url": "/IndexedDB/idbdatabase_createObjectStore8-parameters.htm" + }, + { "path": "IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm", "timeout": "long", "url": "/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm" @@ -18820,6 +18853,71 @@ "url": "/XMLHttpRequest/send-redirect-bogus.htm" }, { + "path": "XMLHttpRequest/xmlhttprequest-timeout-aborted.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-aborted.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-overrides.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-overrides.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-simple.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-simple.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-synconmain.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-twice.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-twice.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html" + }, + { + "path": "XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html", + "timeout": "long", + "url": "/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html" + }, + { "path": "ambient-light/AmbientLight_tests.html", "timeout": "long", "url": "/ambient-light/AmbientLight_tests.html" @@ -19875,6 +19973,36 @@ "url": "/media-source/mediasource-redundant-seek.html" }, { + "path": "service-workers/cache-storage/serviceworker/cache-match.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/serviceworker/cache-match.https.html" + }, + { + "path": "service-workers/cache-storage/serviceworker/cache-put.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/serviceworker/cache-put.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-match.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/window/cache-match.https.html" + }, + { + "path": "service-workers/cache-storage/window/cache-put.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/window/cache-put.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-match.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/worker/cache-match.https.html" + }, + { + "path": "service-workers/cache-storage/worker/cache-put.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/worker/cache-put.https.html" + }, + { "path": "websockets/binary/002.html", "timeout": "long", "url": "/websockets/binary/002.html" @@ -25075,7 +25203,7 @@ } ] }, - "rev": "2a9fd810bb18610b422dbc3998ab74aa1bffae95", + "rev": "000905d008db2538360020335bc2dbba16d322b5", "url_base": "/", "version": 2 }
\ No newline at end of file diff --git a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html.ini b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html.ini new file mode 100644 index 00000000000..ff19591c2a5 --- /dev/null +++ b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html.ini @@ -0,0 +1,3 @@ +[xmlhttprequest-timeout-worker-aborted.html] + type: testharness + expected: TIMEOUT diff --git a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html.ini b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html.ini index 4f2849cb9fb..109458ef6bb 100644 --- a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html.ini +++ b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html.ini @@ -1,5 +1,4 @@ [xmlhttprequest-timeout-worker-overrides.html] type: testharness - [Timeout test: timeout enabled after initially disabled, original timeout at 0, reset at 400 to 1000] - disabled: flaky - https://github.com/w3c/web-platform-tests/issues/1362 + disabled: flaky - https://github.com/w3c/web-platform-tests/issues/1362 diff --git a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html.ini b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html.ini index 0ebda00c863..de2fbbb878d 100644 --- a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html.ini +++ b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html.ini @@ -1,5 +1,4 @@ [xmlhttprequest-timeout-worker-overridesexpires.html] type: testharness - [Timeout test: timeout set to expired value before load fires, original timeout at 1000, reset at 400 to 300] - disabled: racy test + disabled: racy test diff --git a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html.ini b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html.ini new file mode 100644 index 00000000000..746c7d262dc --- /dev/null +++ b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html.ini @@ -0,0 +1,3 @@ +[xmlhttprequest-timeout-worker-simple.html] + type: testharness + expected: TIMEOUT diff --git a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html.ini b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html.ini index 97344145a03..ddda4ae50d2 100644 --- a/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html.ini +++ b/tests/wpt/metadata/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html.ini @@ -1,5 +1,4 @@ [xmlhttprequest-timeout-worker-twice.html] type: testharness - [Timeout test: load fires normally with same timeout set twice, original timeout at 1000, reset at 400 to 1000] - disabled: flaky + disabled: flaky diff --git a/tests/wpt/metadata/dom/interfaces.html.ini b/tests/wpt/metadata/dom/interfaces.html.ini index 5edc29ea9a4..5d8828faeb0 100644 --- a/tests/wpt/metadata/dom/interfaces.html.ini +++ b/tests/wpt/metadata/dom/interfaces.html.ini @@ -96,12 +96,6 @@ [Document interface: operation createTreeWalker(Node,unsigned long,NodeFilter)] expected: FAIL - [Document interface: operation prepend([object Object\],[object Object\])] - expected: FAIL - - [Document interface: operation append([object Object\],[object Object\])] - expected: FAIL - [Document interface: operation query(DOMString)] expected: FAIL @@ -156,12 +150,6 @@ [DocumentFragment interface: operation getElementById(DOMString)] expected: FAIL - [DocumentFragment interface: operation prepend([object Object\],[object Object\])] - expected: FAIL - - [DocumentFragment interface: operation append([object Object\],[object Object\])] - expected: FAIL - [DocumentFragment interface: operation query(DOMString)] expected: FAIL @@ -174,15 +162,9 @@ [DocumentFragment interface: calling getElementById(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError] expected: FAIL - [DocumentFragment interface: document.createDocumentFragment() must inherit property "prepend" with the proper type (5)] - expected: FAIL - [DocumentFragment interface: calling prepend([object Object\],[object Object\]) on document.createDocumentFragment() with too few arguments must throw TypeError] expected: FAIL - [DocumentFragment interface: document.createDocumentFragment() must inherit property "append" with the proper type (6)] - expected: FAIL - [DocumentFragment interface: calling append([object Object\],[object Object\]) on document.createDocumentFragment() with too few arguments must throw TypeError] expected: FAIL @@ -198,21 +180,9 @@ [DocumentFragment interface: calling queryAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError] expected: FAIL - [DocumentType interface: operation before([object Object\],[object Object\])] - expected: FAIL - - [DocumentType interface: operation after([object Object\],[object Object\])] - expected: FAIL - - [DocumentType interface: document.doctype must inherit property "before" with the proper type (3)] - expected: FAIL - [DocumentType interface: calling before([object Object\],[object Object\]) on document.doctype with too few arguments must throw TypeError] expected: FAIL - [DocumentType interface: document.doctype must inherit property "after" with the proper type (4)] - expected: FAIL - [DocumentType interface: calling after([object Object\],[object Object\]) on document.doctype with too few arguments must throw TypeError] expected: FAIL @@ -234,24 +204,12 @@ [Element interface: operation removeAttributeNode(Attr)] expected: FAIL - [Element interface: operation prepend([object Object\],[object Object\])] - expected: FAIL - - [Element interface: operation append([object Object\],[object Object\])] - expected: FAIL - [Element interface: operation query(DOMString)] expected: FAIL [Element interface: operation queryAll(DOMString)] expected: FAIL - [Element interface: operation before([object Object\],[object Object\])] - expected: FAIL - - [Element interface: operation after([object Object\],[object Object\])] - expected: FAIL - [Element interface: element must inherit property "hasAttributes" with the proper type (7)] expected: FAIL @@ -285,15 +243,9 @@ [Element interface: calling removeAttributeNode(Attr) on element with too few arguments must throw TypeError] expected: FAIL - [Element interface: element must inherit property "prepend" with the proper type (31)] - expected: FAIL - [Element interface: calling prepend([object Object\],[object Object\]) on element with too few arguments must throw TypeError] expected: FAIL - [Element interface: element must inherit property "append" with the proper type (32)] - expected: FAIL - [Element interface: calling append([object Object\],[object Object\]) on element with too few arguments must throw TypeError] expected: FAIL @@ -309,15 +261,9 @@ [Element interface: calling queryAll(DOMString) on element with too few arguments must throw TypeError] expected: FAIL - [Element interface: element must inherit property "before" with the proper type (39)] - expected: FAIL - [Element interface: calling before([object Object\],[object Object\]) on element with too few arguments must throw TypeError] expected: FAIL - [Element interface: element must inherit property "after" with the proper type (40)] - expected: FAIL - [Element interface: calling after([object Object\],[object Object\]) on element with too few arguments must throw TypeError] expected: FAIL @@ -327,12 +273,6 @@ [NamedNodeMap interface: operation setNamedItemNS(Attr)] expected: FAIL - [CharacterData interface: operation before([object Object\],[object Object\])] - expected: FAIL - - [CharacterData interface: operation after([object Object\],[object Object\])] - expected: FAIL - [Text interface object length] expected: FAIL @@ -345,42 +285,24 @@ [Text interface: calling splitText(unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: document.createTextNode("abc") must inherit property "before" with the proper type (9)] - expected: FAIL - [CharacterData interface: calling before([object Object\],[object Object\]) on document.createTextNode("abc") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: document.createTextNode("abc") must inherit property "after" with the proper type (10)] - expected: FAIL - [CharacterData interface: calling after([object Object\],[object Object\]) on document.createTextNode("abc") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "before" with the proper type (9)] - expected: FAIL - [CharacterData interface: calling before([object Object\],[object Object\]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "after" with the proper type (10)] - expected: FAIL - [CharacterData interface: calling after([object Object\],[object Object\]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError] expected: FAIL [Comment interface object length] expected: FAIL - [CharacterData interface: document.createComment("abc") must inherit property "before" with the proper type (9)] - expected: FAIL - [CharacterData interface: calling before([object Object\],[object Object\]) on document.createComment("abc") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: document.createComment("abc") must inherit property "after" with the proper type (10)] - expected: FAIL - [CharacterData interface: calling after([object Object\],[object Object\]) on document.createComment("abc") with too few arguments must throw TypeError] expected: FAIL @@ -885,12 +807,6 @@ [Document interface: xmlDoc must inherit property "createNodeIterator" with the proper type (25)] expected: FAIL - [Document interface: xmlDoc must inherit property "prepend" with the proper type (32)] - expected: FAIL - - [Document interface: xmlDoc must inherit property "append" with the proper type (33)] - expected: FAIL - [Document interface: xmlDoc must inherit property "query" with the proper type (34)] expected: FAIL @@ -927,42 +843,18 @@ [Comment interface: existence and properties of interface object] expected: FAIL - [DocumentType interface: operation replaceWith([object Object\],[object Object\])] - expected: FAIL - - [DocumentType interface: document.doctype must inherit property "replaceWith" with the proper type (5)] - expected: FAIL - [DocumentType interface: calling replaceWith([object Object\],[object Object\]) on document.doctype with too few arguments must throw TypeError] expected: FAIL - [Element interface: operation replaceWith([object Object\],[object Object\])] - expected: FAIL - - [Element interface: element must inherit property "replaceWith" with the proper type (41)] - expected: FAIL - [Element interface: calling replaceWith([object Object\],[object Object\]) on element with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: operation replaceWith([object Object\],[object Object\])] - expected: FAIL - - [CharacterData interface: document.createTextNode("abc") must inherit property "replaceWith" with the proper type (11)] - expected: FAIL - [CharacterData interface: calling replaceWith([object Object\],[object Object\]) on document.createTextNode("abc") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceWith" with the proper type (11)] - expected: FAIL - [CharacterData interface: calling replaceWith([object Object\],[object Object\]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError] expected: FAIL - [CharacterData interface: document.createComment("abc") must inherit property "replaceWith" with the proper type (11)] - expected: FAIL - [CharacterData interface: calling replaceWith([object Object\],[object Object\]) on document.createComment("abc") with too few arguments must throw TypeError] expected: FAIL diff --git a/tests/wpt/metadata/dom/nodes/getElementsByClassName-31.htm.ini b/tests/wpt/metadata/dom/nodes/getElementsByClassName-31.htm.ini deleted file mode 100644 index b98e9fc58e1..00000000000 --- a/tests/wpt/metadata/dom/nodes/getElementsByClassName-31.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[getElementsByClassName-31.htm] - type: testharness - [getElementsByClassName across documents] - expected: PASS - diff --git a/tests/wpt/metadata/encoding/api-replacement-encodings.html.ini b/tests/wpt/metadata/encoding/api-replacement-encodings.html.ini index b890466bae1..99468e76336 100644 --- a/tests/wpt/metadata/encoding/api-replacement-encodings.html.ini +++ b/tests/wpt/metadata/encoding/api-replacement-encodings.html.ini @@ -2,3 +2,4 @@ type: testharness [Label for "replacement" should be rejected by API: hz-gb-2312] expected: FAIL + diff --git a/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini b/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini index 4c84622faf8..d186734577b 100644 --- a/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini +++ b/tests/wpt/metadata/encoding/textencoder-constructor-non-utf.html.ini @@ -5,3 +5,4 @@ [UTF encodings are supported for encode and decode: utf-16le] expected: FAIL + diff --git a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini index 2afe1779b49..68049100081 100644 --- a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini +++ b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini @@ -1,14 +1,5 @@ [window-properties.html] type: testharness - [EventTarget method: addEventListener] - expected: FAIL - - [EventTarget method: removeEventListener] - expected: FAIL - - [EventTarget method: dispatchEvent] - expected: FAIL - [Window method: close] expected: FAIL @@ -78,18 +69,12 @@ [Window readonly attribute: history] expected: FAIL - [Window readonly attribute: parent] - expected: FAIL - [Window readonly attribute: frameElement] expected: FAIL [Window readonly attribute: navigator] expected: FAIL - [Window readonly attribute: external] - expected: FAIL - [Window readonly attribute: applicationCache] expected: FAIL @@ -99,39 +84,6 @@ [Window readonly attribute: localStorage] expected: FAIL - [Window readonly attribute: screen] - expected: FAIL - - [Window readonly attribute: innerWidth] - expected: FAIL - - [Window readonly attribute: innerHeight] - expected: FAIL - - [Window readonly attribute: scrollX] - expected: FAIL - - [Window readonly attribute: pageXOffset] - expected: FAIL - - [Window readonly attribute: scrollY] - expected: FAIL - - [Window readonly attribute: pageYOffset] - expected: FAIL - - [Window readonly attribute: screenX] - expected: FAIL - - [Window readonly attribute: screenY] - expected: FAIL - - [Window readonly attribute: outerWidth] - expected: FAIL - - [Window readonly attribute: outerHeight] - expected: FAIL - [Window attribute: name] expected: FAIL @@ -384,3 +336,45 @@ [Window replaceable attribute: length] expected: FAIL + [Window replaceable attribute: parent] + expected: FAIL + + [Window replaceable attribute: external] + expected: FAIL + + [Window replaceable attribute: screen] + expected: FAIL + + [Window replaceable attribute: scrollX] + expected: FAIL + + [Window replaceable attribute: scrollY] + expected: FAIL + + [Window replaceable attribute: pageXOffset] + expected: FAIL + + [Window replaceable attribute: pageYOffset] + expected: FAIL + + [Window replaceable attribute: innerWidth] + expected: FAIL + + [Window replaceable attribute: innerHeight] + expected: FAIL + + [Window replaceable attribute: screenX] + expected: FAIL + + [Window replaceable attribute: screenY] + expected: FAIL + + [Window replaceable attribute: outerWidth] + expected: FAIL + + [Window replaceable attribute: outerHeight] + expected: FAIL + + [Window replaceable attribute: devicePixelRatio] + expected: FAIL + diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index 2e2eeeca4cf..62800c0b7e8 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -1185,15 +1185,9 @@ [Document interface: document.implementation.createDocument(null, "", null) must inherit property "all" with the proper type (81)] expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "prepend" with the proper type (87)] - expected: FAIL - [Document interface: calling prepend([object Object\],[object Object\]) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError] expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "append" with the proper type (88)] - expected: FAIL - [Document interface: calling append([object Object\],[object Object\]) on document.implementation.createDocument(null, "", null) with too few arguments must throw TypeError] expected: FAIL @@ -2190,15 +2184,9 @@ [Element interface: calling removeAttributeNode(Attr) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "prepend" with the proper type (31)] - expected: FAIL - [Element interface: calling prepend([object Object\],[object Object\]) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "append" with the proper type (32)] - expected: FAIL - [Element interface: calling append([object Object\],[object Object\]) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL @@ -2214,15 +2202,9 @@ [Element interface: calling queryAll(DOMString) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "before" with the proper type (39)] - expected: FAIL - [Element interface: calling before([object Object\],[object Object\]) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "after" with the proper type (40)] - expected: FAIL - [Element interface: calling after([object Object\],[object Object\]) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL @@ -6888,12 +6870,6 @@ [CanvasRenderingContext2D interface: operation commit()] expected: FAIL - [CanvasRenderingContext2D interface: operation save()] - expected: FAIL - - [CanvasRenderingContext2D interface: operation restore()] - expected: FAIL - [CanvasRenderingContext2D interface: attribute currentTransform] expected: FAIL @@ -7017,9 +6993,6 @@ [CanvasRenderingContext2D interface: operation arcTo(unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double)] expected: FAIL - [CanvasRenderingContext2D interface: operation rect(unrestricted double,unrestricted double,unrestricted double,unrestricted double)] - expected: FAIL - [CanvasRenderingContext2D interface: operation arc(unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,boolean)] expected: FAIL @@ -7035,12 +7008,6 @@ [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "commit" with the proper type (3)] expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "save" with the proper type (4)] - expected: FAIL - - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "restore" with the proper type (5)] - expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "currentTransform" with the proper type (6)] expected: FAIL @@ -7221,12 +7188,6 @@ [CanvasRenderingContext2D interface: calling arcTo(unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double,unrestricted double) on document.createElement("canvas").getContext("2d") with too few arguments must throw TypeError] expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "rect" with the proper type (77)] - expected: FAIL - - [CanvasRenderingContext2D interface: calling rect(unrestricted double,unrestricted double,unrestricted double,unrestricted double) on document.createElement("canvas").getContext("2d") with too few arguments must throw TypeError] - expected: FAIL - [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "ellipse" with the proper type (79)] expected: FAIL @@ -9519,9 +9480,6 @@ [HTMLFontElement interface: document.createElement("font") must inherit property "size" with the proper type (2)] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "replaceWith" with the proper type (41)] - expected: FAIL - [Element interface: calling replaceWith([object Object\],[object Object\]) on document.createElement("noscript") with too few arguments must throw TypeError] expected: FAIL diff --git a/tests/wpt/metadata/html/dom/reflection-embedded.html.ini b/tests/wpt/metadata/html/dom/reflection-embedded.html.ini index d08babcf760..5c5fabe56ad 100644 --- a/tests/wpt/metadata/html/dom/reflection-embedded.html.ini +++ b/tests/wpt/metadata/html/dom/reflection-embedded.html.ini @@ -1131,24 +1131,6 @@ [img.hspace: setAttribute() to 4294967295 followed by IDL get] expected: FAIL - [img.hspace: setAttribute() to "\\t7" followed by IDL get] - expected: FAIL - - [img.hspace: setAttribute() to "\\f7" followed by IDL get] - expected: FAIL - - [img.hspace: setAttribute() to " 7" followed by IDL get] - expected: FAIL - - [img.hspace: setAttribute() to "\\n7" followed by IDL get] - expected: FAIL - - [img.hspace: setAttribute() to "\\r7" followed by IDL get] - expected: FAIL - - [img.hspace: setAttribute() to 1.5 followed by IDL get] - expected: FAIL - [img.hspace: setAttribute() to object "3" followed by getAttribute()] expected: FAIL @@ -1161,24 +1143,6 @@ [img.vspace: setAttribute() to 4294967295 followed by IDL get] expected: FAIL - [img.vspace: setAttribute() to "\\t7" followed by IDL get] - expected: FAIL - - [img.vspace: setAttribute() to "\\f7" followed by IDL get] - expected: FAIL - - [img.vspace: setAttribute() to " 7" followed by IDL get] - expected: FAIL - - [img.vspace: setAttribute() to "\\n7" followed by IDL get] - expected: FAIL - - [img.vspace: setAttribute() to "\\r7" followed by IDL get] - expected: FAIL - - [img.vspace: setAttribute() to 1.5 followed by IDL get] - expected: FAIL - [img.vspace: setAttribute() to object "3" followed by getAttribute()] expected: FAIL diff --git a/tests/wpt/metadata/html/dom/reflection-forms.html.ini b/tests/wpt/metadata/html/dom/reflection-forms.html.ini index d336d9b06ec..4a471e82393 100644 --- a/tests/wpt/metadata/html/dom/reflection-forms.html.ini +++ b/tests/wpt/metadata/html/dom/reflection-forms.html.ini @@ -5778,25 +5778,10 @@ [input.size: setAttribute() to 4294967295 followed by IDL get] expected: FAIL - [input.size: setAttribute() to "0" followed by IDL get] - expected: FAIL - - [input.size: setAttribute() to "\\t7" followed by IDL get] - expected: FAIL - - [input.size: setAttribute() to "\\f7" followed by IDL get] - expected: FAIL - - [input.size: setAttribute() to " 7" followed by IDL get] - expected: FAIL - - [input.size: setAttribute() to "\\n7" followed by IDL get] + [input.size: setAttribute() to "-0" followed by IDL get] expected: FAIL - [input.size: setAttribute() to "\\r7" followed by IDL get] - expected: FAIL - - [input.size: setAttribute() to 1.5 followed by IDL get] + [input.size: setAttribute() to "0" followed by IDL get] expected: FAIL [input.size: setAttribute() to object "3" followed by getAttribute()] @@ -12228,25 +12213,10 @@ [textarea.cols: setAttribute() to 4294967295 followed by IDL get] expected: FAIL - [textarea.cols: setAttribute() to "0" followed by IDL get] - expected: FAIL - - [textarea.cols: setAttribute() to "\\t7" followed by IDL get] - expected: FAIL - - [textarea.cols: setAttribute() to "\\f7" followed by IDL get] - expected: FAIL - - [textarea.cols: setAttribute() to " 7" followed by IDL get] - expected: FAIL - - [textarea.cols: setAttribute() to "\\n7" followed by IDL get] - expected: FAIL - - [textarea.cols: setAttribute() to "\\r7" followed by IDL get] + [textarea.cols: setAttribute() to "-0" followed by IDL get] expected: FAIL - [textarea.cols: setAttribute() to 1.5 followed by IDL get] + [textarea.cols: setAttribute() to "0" followed by IDL get] expected: FAIL [textarea.cols: setAttribute() to object "3" followed by getAttribute()] @@ -13179,25 +13149,10 @@ [textarea.rows: setAttribute() to 4294967295 followed by IDL get] expected: FAIL - [textarea.rows: setAttribute() to "0" followed by IDL get] - expected: FAIL - - [textarea.rows: setAttribute() to "\\t7" followed by IDL get] + [textarea.rows: setAttribute() to "-0" followed by IDL get] expected: FAIL - [textarea.rows: setAttribute() to "\\f7" followed by IDL get] - expected: FAIL - - [textarea.rows: setAttribute() to " 7" followed by IDL get] - expected: FAIL - - [textarea.rows: setAttribute() to "\\n7" followed by IDL get] - expected: FAIL - - [textarea.rows: setAttribute() to "\\r7" followed by IDL get] - expected: FAIL - - [textarea.rows: setAttribute() to 1.5 followed by IDL get] + [textarea.rows: setAttribute() to "0" followed by IDL get] expected: FAIL [textarea.rows: setAttribute() to object "3" followed by getAttribute()] diff --git a/tests/wpt/metadata/html/dom/reflection-misc.html.ini b/tests/wpt/metadata/html/dom/reflection-misc.html.ini index d7000629e79..c3fcda41468 100644 --- a/tests/wpt/metadata/html/dom/reflection-misc.html.ini +++ b/tests/wpt/metadata/html/dom/reflection-misc.html.ini @@ -12375,3 +12375,843 @@ [menu.type: IDL set to "TOOLBAR" followed by IDL get] expected: FAIL + [dialog.dir: typeof IDL attribute] + expected: FAIL + + [dialog.dir: IDL get with DOM attribute unset] + expected: FAIL + + [dialog.dir: setAttribute() to "" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to undefined followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to 7 followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to 1.5 followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to true followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to false followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to NaN followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to Infinity followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to -Infinity followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to null followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "ltr" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "xltr" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "ltr\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "tr" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "LTR" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "rtl" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "xrtl" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "rtl\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "tl" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "RTL" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "auto" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "xauto" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "auto\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "uto" followed by IDL get] + expected: FAIL + + [dialog.dir: setAttribute() to "AUTO" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to undefined followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to undefined followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to 7 followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to 7 followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to 1.5 followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to 1.5 followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to true followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to true followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to false followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to false followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to object "[object Object\]" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to NaN followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to NaN followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to Infinity followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to Infinity followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to -Infinity followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to -Infinity followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "\\0" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to null followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to object "test-toString" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to object "test-valueOf" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "ltr" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "xltr" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "xltr" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "ltr\\0" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "ltr\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "tr" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "tr" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "LTR" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "LTR" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "rtl" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "xrtl" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "xrtl" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "rtl\\0" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "rtl\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "tl" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "tl" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "RTL" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "RTL" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "auto" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "xauto" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "xauto" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "auto\\0" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "auto\\0" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "uto" followed by getAttribute()] + expected: FAIL + + [dialog.dir: IDL set to "uto" followed by IDL get] + expected: FAIL + + [dialog.dir: IDL set to "AUTO" followed by IDL get] + expected: FAIL + + [dialog.accessKey: typeof IDL attribute] + expected: FAIL + + [dialog.accessKey: IDL get with DOM attribute unset] + expected: FAIL + + [dialog.accessKey: setAttribute() to "" followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to undefined followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to 7 followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to 1.5 followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to true followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to false followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to NaN followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to Infinity followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to -Infinity followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to "\\0" followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to null followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.accessKey: setAttribute() to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to "" followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to undefined followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to undefined followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to 7 followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to 7 followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to 1.5 followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to 1.5 followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to true followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to true followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to false followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to false followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to object "[object Object\]" followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to NaN followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to NaN followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to Infinity followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to Infinity followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to -Infinity followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to -Infinity followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to "\\0" followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to null followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to null followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to object "test-toString" followed by getAttribute()] + expected: FAIL + + [dialog.accessKey: IDL set to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.accessKey: IDL set to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: typeof IDL attribute] + expected: FAIL + + [dialog.tabIndex: setAttribute() to -36 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to -1 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to 0 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to 1 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to 2147483647 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to -2147483648 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "-1" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "-0" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "0" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "1" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "\\t7" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "\\f7" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to " 7" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "\\n7" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to "\\r7" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to 1.5 followed by IDL get] + expected: FAIL + + [dialog.tabIndex: setAttribute() to object "2" followed by IDL get] + expected: FAIL + + [dialog.tabIndex: IDL set to -36 followed by getAttribute()] + expected: FAIL + + [dialog.tabIndex: IDL set to -1 followed by getAttribute()] + expected: FAIL + + [dialog.tabIndex: IDL set to 0 followed by getAttribute()] + expected: FAIL + + [dialog.tabIndex: IDL set to 1 followed by getAttribute()] + expected: FAIL + + [dialog.tabIndex: IDL set to 2147483647 followed by getAttribute()] + expected: FAIL + + [dialog.tabIndex: IDL set to -2147483648 followed by getAttribute()] + expected: FAIL + + [dialog.open: typeof IDL attribute] + expected: FAIL + + [dialog.open: IDL get with DOM attribute unset] + expected: FAIL + + [dialog.open: setAttribute() to "" followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to " foo " followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to undefined followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to null followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to 7 followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to 1.5 followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to true followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to false followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to NaN followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to Infinity followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to -Infinity followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to "\\0" followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.open: setAttribute() to "open" followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to "" followed by hasAttribute()] + expected: FAIL + + [dialog.open: IDL set to "" followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to " foo " followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to undefined followed by hasAttribute()] + expected: FAIL + + [dialog.open: IDL set to undefined followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to null followed by hasAttribute()] + expected: FAIL + + [dialog.open: IDL set to null followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to 7 followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to 1.5 followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to false followed by hasAttribute()] + expected: FAIL + + [dialog.open: IDL set to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to NaN followed by hasAttribute()] + expected: FAIL + + [dialog.open: IDL set to NaN followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to Infinity followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to -Infinity followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to "\\0" followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.open: IDL set to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.itemScope: typeof IDL attribute] + expected: FAIL + + [dialog.itemScope: IDL get with DOM attribute unset] + expected: FAIL + + [dialog.itemScope: setAttribute() to "" followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to " foo " followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to undefined followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to null followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to 7 followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to 1.5 followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to true followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to false followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to NaN followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to Infinity followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to -Infinity followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to "\\0" followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.itemScope: setAttribute() to "itemScope" followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to "" followed by hasAttribute()] + expected: FAIL + + [dialog.itemScope: IDL set to "" followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to " foo " followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to undefined followed by hasAttribute()] + expected: FAIL + + [dialog.itemScope: IDL set to undefined followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to null followed by hasAttribute()] + expected: FAIL + + [dialog.itemScope: IDL set to null followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to 7 followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to 1.5 followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to false followed by hasAttribute()] + expected: FAIL + + [dialog.itemScope: IDL set to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to NaN followed by hasAttribute()] + expected: FAIL + + [dialog.itemScope: IDL set to NaN followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to Infinity followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to -Infinity followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to "\\0" followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.itemScope: IDL set to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.itemId: typeof IDL attribute] + expected: FAIL + + [dialog.itemId: IDL get with DOM attribute unset] + expected: FAIL + + [dialog.itemId: setAttribute() to "" followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to " foo " followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to "http://site.example/" followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to "//site.example/path???@#l" followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to "\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f " followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to undefined followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to 7 followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to 1.5 followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to true followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to false followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to NaN followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to Infinity followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to -Infinity followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to "\\0" followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to null followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.itemId: setAttribute() to object "test-valueOf" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to "" followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to "" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to " foo " followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to " foo " followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to "http://site.example/" followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to "http://site.example/" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to "//site.example/path???@#l" followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to "//site.example/path???@#l" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to "\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f " followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to "\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f " followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to undefined followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to undefined followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to 7 followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to 7 followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to 1.5 followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to 1.5 followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to true followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to true followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to false followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to false followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to object "[object Object\]" followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to object "[object Object\]" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to NaN followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to NaN followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to Infinity followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to Infinity followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to -Infinity followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to -Infinity followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to "\\0" followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to "\\0" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to null followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to null followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to object "test-toString" followed by getAttribute()] + expected: FAIL + + [dialog.itemId: IDL set to object "test-toString" followed by IDL get] + expected: FAIL + + [dialog.itemId: IDL set to object "test-valueOf" followed by IDL get] + expected: FAIL + diff --git a/tests/wpt/metadata/html/semantics/selectors/pseudo-classes/focus.html.ini b/tests/wpt/metadata/html/semantics/selectors/pseudo-classes/focus.html.ini index 25bc6b23c6a..f21d3ab17c8 100644 --- a/tests/wpt/metadata/html/semantics/selectors/pseudo-classes/focus.html.ini +++ b/tests/wpt/metadata/html/semantics/selectors/pseudo-classes/focus.html.ini @@ -2,10 +2,13 @@ type: testharness [input3 has the attribute autofocus] expected: FAIL + [tabindex attribute makes the element focusable] expected: FAIL + [editable elements are focusable] expected: FAIL - [':focus' matches focussed body with tabindex] + + [\':focus\' matches focussed body with tabindex] expected: FAIL diff --git a/tests/wpt/metadata/mozilla-sync b/tests/wpt/metadata/mozilla-sync new file mode 100644 index 00000000000..de8ec6fd4e4 --- /dev/null +++ b/tests/wpt/metadata/mozilla-sync @@ -0,0 +1 @@ +53d2432c90ab9ef171dfbef8e22ed3f58fcef8f0 diff --git a/tests/wpt/metadata/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js.ini b/tests/wpt/metadata/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js.ini deleted file mode 100644 index fc8a5d52bc8..00000000000 --- a/tests/wpt/metadata/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js.ini +++ /dev/null @@ -1,5 +0,0 @@ -[EventTarget.worker] - type: testharness - [removeEventListener] - expected: FAIL - diff --git a/tests/wpt/metadata/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html.ini b/tests/wpt/metadata/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html.ini index 802671023a3..508a59a7c22 100644 --- a/tests/wpt/metadata/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html.ini +++ b/tests/wpt/metadata/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html.ini @@ -1,5 +1,6 @@ [propagate-to-window-onerror.html] type: testharness + expected: TIMEOUT [onerror, "not handled" with only window.onerror defined] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 506e7b62b7d..efd18936509 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -13,11 +13,539 @@ }, "local_changes": { "deleted": [], - "items": {}, - "reftest_nodes": {} + "items": { + "reftest": { + "css/class-namespaces.html": [ + { + "path": "css/class-namespaces.html", + "references": [ + [ + "/_mozilla/css/class-namespaces-ref.html", + "==" + ] + ], + "url": "/_mozilla/css/class-namespaces.html" + } + ] + }, + "testharness": { + "mozilla/DOMParser.html": [ + { + "path": "mozilla/DOMParser.html", + "url": "/_mozilla/mozilla/DOMParser.html" + } + ], + "mozilla/Event.html": [ + { + "path": "mozilla/Event.html", + "url": "/_mozilla/mozilla/Event.html" + } + ], + "mozilla/MouseEvent.html": [ + { + "path": "mozilla/MouseEvent.html", + "url": "/_mozilla/mozilla/MouseEvent.html" + } + ], + "mozilla/blob.html": [ + { + "path": "mozilla/blob.html", + "url": "/_mozilla/mozilla/blob.html" + } + ], + "mozilla/body_listener.html": [ + { + "path": "mozilla/body_listener.html", + "url": "/_mozilla/mozilla/body_listener.html" + } + ], + "mozilla/caption.html": [ + { + "path": "mozilla/caption.html", + "url": "/_mozilla/mozilla/caption.html" + } + ], + "mozilla/characterdata.html": [ + { + "path": "mozilla/characterdata.html", + "url": "/_mozilla/mozilla/characterdata.html" + } + ], + "mozilla/collections.html": [ + { + "path": "mozilla/collections.html", + "url": "/_mozilla/mozilla/collections.html" + } + ], + "mozilla/createElement_script.html": [ + { + "path": "mozilla/createElement_script.html", + "url": "/_mozilla/mozilla/createElement_script.html" + } + ], + "mozilla/create_element.html": [ + { + "path": "mozilla/create_element.html", + "url": "/_mozilla/mozilla/create_element.html" + } + ], + "mozilla/documentElement.html": [ + { + "path": "mozilla/documentElement.html", + "url": "/_mozilla/mozilla/documentElement.html" + } + ], + "mozilla/document_activeElement.html": [ + { + "path": "mozilla/document_activeElement.html", + "url": "/_mozilla/mozilla/document_activeElement.html" + } + ], + "mozilla/document_body.html": [ + { + "path": "mozilla/document_body.html", + "url": "/_mozilla/mozilla/document_body.html" + } + ], + "mozilla/document_characterSet.html": [ + { + "path": "mozilla/document_characterSet.html", + "url": "/_mozilla/mozilla/document_characterSet.html" + } + ], + "mozilla/document_characterSet_default.html": [ + { + "path": "mozilla/document_characterSet_default.html", + "url": "/_mozilla/mozilla/document_characterSet_default.html" + } + ], + "mozilla/document_characterSet_invalid.html": [ + { + "path": "mozilla/document_characterSet_invalid.html", + "url": "/_mozilla/mozilla/document_characterSet_invalid.html" + } + ], + "mozilla/document_characterSet_long.html": [ + { + "path": "mozilla/document_characterSet_long.html", + "url": "/_mozilla/mozilla/document_characterSet_long.html" + } + ], + "mozilla/document_characterSet_short.html": [ + { + "path": "mozilla/document_characterSet_short.html", + "url": "/_mozilla/mozilla/document_characterSet_short.html" + } + ], + "mozilla/document_compatMode_loose.html": [ + { + "path": "mozilla/document_compatMode_loose.html", + "url": "/_mozilla/mozilla/document_compatMode_loose.html" + } + ], + "mozilla/document_compatMode_strict.html": [ + { + "path": "mozilla/document_compatMode_strict.html", + "url": "/_mozilla/mozilla/document_compatMode_strict.html" + } + ], + "mozilla/document_contenttype.html": [ + { + "path": "mozilla/document_contenttype.html", + "url": "/_mozilla/mozilla/document_contenttype.html" + } + ], + "mozilla/document_datalist_options.html": [ + { + "path": "mozilla/document_datalist_options.html", + "url": "/_mozilla/mozilla/document_datalist_options.html" + } + ], + "mozilla/document_defaultView.html": [ + { + "path": "mozilla/document_defaultView.html", + "url": "/_mozilla/mozilla/document_defaultView.html" + } + ], + "mozilla/document_getElementById.html": [ + { + "path": "mozilla/document_getElementById.html", + "url": "/_mozilla/mozilla/document_getElementById.html" + } + ], + "mozilla/document_getElementsByName.html": [ + { + "path": "mozilla/document_getElementsByName.html", + "url": "/_mozilla/mozilla/document_getElementsByName.html" + } + ], + "mozilla/document_head.html": [ + { + "path": "mozilla/document_head.html", + "url": "/_mozilla/mozilla/document_head.html" + } + ], + "mozilla/document_images_cache.html": [ + { + "path": "mozilla/document_images_cache.html", + "url": "/_mozilla/mozilla/document_images_cache.html" + } + ], + "mozilla/document_implementation.html": [ + { + "path": "mozilla/document_implementation.html", + "url": "/_mozilla/mozilla/document_implementation.html" + } + ], + "mozilla/document_links_cache.html": [ + { + "path": "mozilla/document_links_cache.html", + "url": "/_mozilla/mozilla/document_links_cache.html" + } + ], + "mozilla/document_readystate.html": [ + { + "path": "mozilla/document_readystate.html", + "url": "/_mozilla/mozilla/document_readystate.html" + } + ], + "mozilla/document_set_node_value.html": [ + { + "path": "mozilla/document_set_node_value.html", + "url": "/_mozilla/mozilla/document_set_node_value.html" + } + ], + "mozilla/document_title_nontextchildren.html": [ + { + "path": "mozilla/document_title_nontextchildren.html", + "url": "/_mozilla/mozilla/document_title_nontextchildren.html" + } + ], + "mozilla/document_url.html": [ + { + "path": "mozilla/document_url.html", + "url": "/_mozilla/mozilla/document_url.html" + } + ], + "mozilla/domtokenlist.html": [ + { + "path": "mozilla/domtokenlist.html", + "url": "/_mozilla/mozilla/domtokenlist.html" + } + ], + "mozilla/element_attribute.html": [ + { + "path": "mozilla/element_attribute.html", + "url": "/_mozilla/mozilla/element_attribute.html" + } + ], + "mozilla/element_attributes.html": [ + { + "path": "mozilla/element_attributes.html", + "url": "/_mozilla/mozilla/element_attributes.html" + } + ], + "mozilla/element_classList.html": [ + { + "path": "mozilla/element_classList.html", + "url": "/_mozilla/mozilla/element_classList.html" + } + ], + "mozilla/element_className.html": [ + { + "path": "mozilla/element_className.html", + "url": "/_mozilla/mozilla/element_className.html" + } + ], + "mozilla/element_matches.html": [ + { + "path": "mozilla/element_matches.html", + "url": "/_mozilla/mozilla/element_matches.html" + } + ], + "mozilla/empty_clientrect.html": [ + { + "path": "mozilla/empty_clientrect.html", + "url": "/_mozilla/mozilla/empty_clientrect.html" + } + ], + "mozilla/enabled_disabled_selectors.html": [ + { + "path": "mozilla/enabled_disabled_selectors.html", + "url": "/_mozilla/mozilla/enabled_disabled_selectors.html" + } + ], + "mozilla/event_dispatch.html": [ + { + "path": "mozilla/event_dispatch.html", + "url": "/_mozilla/mozilla/event_dispatch.html" + } + ], + "mozilla/event_dispatch_dynamic.html": [ + { + "path": "mozilla/event_dispatch_dynamic.html", + "url": "/_mozilla/mozilla/event_dispatch_dynamic.html" + } + ], + "mozilla/event_dispatch_order.html": [ + { + "path": "mozilla/event_dispatch_order.html", + "url": "/_mozilla/mozilla/event_dispatch_order.html" + } + ], + "mozilla/event_handler_syntax_error.html": [ + { + "path": "mozilla/event_handler_syntax_error.html", + "url": "/_mozilla/mozilla/event_handler_syntax_error.html" + } + ], + "mozilla/event_listener.html": [ + { + "path": "mozilla/event_listener.html", + "url": "/_mozilla/mozilla/event_listener.html" + } + ], + "mozilla/focus_blur.html": [ + { + "path": "mozilla/focus_blur.html", + "url": "/_mozilla/mozilla/focus_blur.html" + } + ], + "mozilla/getBoundingClientRect.html": [ + { + "path": "mozilla/getBoundingClientRect.html", + "url": "/_mozilla/mozilla/getBoundingClientRect.html" + } + ], + "mozilla/getPropertyPriority.html": [ + { + "path": "mozilla/getPropertyPriority.html", + "url": "/_mozilla/mozilla/getPropertyPriority.html" + } + ], + "mozilla/global.html": [ + { + "path": "mozilla/global.html", + "url": "/_mozilla/mozilla/global.html" + } + ], + "mozilla/htmlcollection.html": [ + { + "path": "mozilla/htmlcollection.html", + "url": "/_mozilla/mozilla/htmlcollection.html" + } + ], + "mozilla/htmlfieldsetelement_elements.html": [ + { + "path": "mozilla/htmlfieldsetelement_elements.html", + "url": "/_mozilla/mozilla/htmlfieldsetelement_elements.html" + } + ], + "mozilla/htmlspacechars.html": [ + { + "path": "mozilla/htmlspacechars.html", + "url": "/_mozilla/mozilla/htmlspacechars.html" + } + ], + "mozilla/iframe_contentDocument.html": [ + { + "path": "mozilla/iframe_contentDocument.html", + "url": "/_mozilla/mozilla/iframe_contentDocument.html" + } + ], + "mozilla/img_width_height.html": [ + { + "path": "mozilla/img_width_height.html", + "url": "/_mozilla/mozilla/img_width_height.html" + } + ], + "mozilla/inline_event_handler.html": [ + { + "path": "mozilla/inline_event_handler.html", + "url": "/_mozilla/mozilla/inline_event_handler.html" + } + ], + "mozilla/innerHTML.html": [ + { + "path": "mozilla/innerHTML.html", + "url": "/_mozilla/mozilla/innerHTML.html" + } + ], + "mozilla/interfaces.html": [ + { + "path": "mozilla/interfaces.html", + "url": "/_mozilla/mozilla/interfaces.html" + } + ], + "mozilla/lenient_this.html": [ + { + "path": "mozilla/lenient_this.html", + "url": "/_mozilla/mozilla/lenient_this.html" + } + ], + "mozilla/load_event.html": [ + { + "path": "mozilla/load_event.html", + "url": "/_mozilla/mozilla/load_event.html" + } + ], + "mozilla/navigator.html": [ + { + "path": "mozilla/navigator.html", + "url": "/_mozilla/mozilla/navigator.html" + } + ], + "mozilla/node_cloneNode.html": [ + { + "path": "mozilla/node_cloneNode.html", + "url": "/_mozilla/mozilla/node_cloneNode.html" + } + ], + "mozilla/node_compareDocumentPosition.html": [ + { + "path": "mozilla/node_compareDocumentPosition.html", + "url": "/_mozilla/mozilla/node_compareDocumentPosition.html" + } + ], + "mozilla/node_contains.html": [ + { + "path": "mozilla/node_contains.html", + "url": "/_mozilla/mozilla/node_contains.html" + } + ], + "mozilla/node_insertBefore.html": [ + { + "path": "mozilla/node_insertBefore.html", + "url": "/_mozilla/mozilla/node_insertBefore.html" + } + ], + "mozilla/node_isEqualNode.html": [ + { + "path": "mozilla/node_isEqualNode.html", + "url": "/_mozilla/mozilla/node_isEqualNode.html" + } + ], + "mozilla/node_lookupPrefix.html": [ + { + "path": "mozilla/node_lookupPrefix.html", + "url": "/_mozilla/mozilla/node_lookupPrefix.html" + } + ], + "mozilla/node_normalize.html": [ + { + "path": "mozilla/node_normalize.html", + "url": "/_mozilla/mozilla/node_normalize.html" + } + ], + "mozilla/node_replaceChild.html": [ + { + "path": "mozilla/node_replaceChild.html", + "url": "/_mozilla/mozilla/node_replaceChild.html" + } + ], + "mozilla/parentNode_querySelector.html": [ + { + "path": "mozilla/parentNode_querySelector.html", + "url": "/_mozilla/mozilla/parentNode_querySelector.html" + } + ], + "mozilla/parentNode_querySelectorAll.html": [ + { + "path": "mozilla/parentNode_querySelectorAll.html", + "url": "/_mozilla/mozilla/parentNode_querySelectorAll.html" + } + ], + "mozilla/parentnodes.html": [ + { + "path": "mozilla/parentnodes.html", + "url": "/_mozilla/mozilla/parentnodes.html" + } + ], + "mozilla/proxy_setter.html": [ + { + "path": "mozilla/proxy_setter.html", + "url": "/_mozilla/mozilla/proxy_setter.html" + } + ], + "mozilla/script_type.html": [ + { + "path": "mozilla/script_type.html", + "url": "/_mozilla/mozilla/script_type.html" + } + ], + "mozilla/storage.html": [ + { + "path": "mozilla/storage.html", + "url": "/_mozilla/mozilla/storage.html" + } + ], + "mozilla/textcontent.html": [ + { + "path": "mozilla/textcontent.html", + "url": "/_mozilla/mozilla/textcontent.html" + } + ], + "mozilla/title.html": [ + { + "path": "mozilla/title.html", + "url": "/_mozilla/mozilla/title.html" + } + ], + "mozilla/trace_null.html": [ + { + "path": "mozilla/trace_null.html", + "url": "/_mozilla/mozilla/trace_null.html" + } + ], + "mozilla/union.html": [ + { + "path": "mozilla/union.html", + "url": "/_mozilla/mozilla/union.html" + } + ], + "mozilla/window.html": [ + { + "path": "mozilla/window.html", + "url": "/_mozilla/mozilla/window.html" + } + ], + "mozilla/window_performance.html": [ + { + "path": "mozilla/window_performance.html", + "url": "/_mozilla/mozilla/window_performance.html" + } + ], + "mozilla/window_setInterval.html": [ + { + "path": "mozilla/window_setInterval.html", + "url": "/_mozilla/mozilla/window_setInterval.html" + } + ], + "mozilla/windowproxy.html": [ + { + "path": "mozilla/windowproxy.html", + "url": "/_mozilla/mozilla/windowproxy.html" + } + ] + } + }, + "reftest_nodes": { + "css/class-namespaces.html": [ + { + "path": "css/class-namespaces.html", + "references": [ + [ + "/_mozilla/css/class-namespaces-ref.html", + "==" + ] + ], + "url": "/_mozilla/css/class-namespaces.html" + } + ] + } }, "reftest_nodes": {}, "rev": null, "url_base": "/_mozilla/", "version": 2 -} +}
\ No newline at end of file diff --git a/tests/wpt/mozilla/meta/mozilla/document_characterSet_long.html.ini b/tests/wpt/mozilla/meta/mozilla/document_characterSet_long.html.ini new file mode 100644 index 00000000000..79923c15fb6 --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/document_characterSet_long.html.ini @@ -0,0 +1,5 @@ +[document_characterSet_long.html] + type: testharness + [Untitled] + expected: FAIL + diff --git a/tests/wpt/mozilla/meta/mozilla/document_characterSet_short.html.ini b/tests/wpt/mozilla/meta/mozilla/document_characterSet_short.html.ini new file mode 100644 index 00000000000..c6d6561a99b --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/document_characterSet_short.html.ini @@ -0,0 +1,5 @@ +[document_characterSet_short.html] + type: testharness + [Untitled] + expected: FAIL + diff --git a/tests/wpt/mozilla/meta/mozilla/enabled_disabled_selectors.html.ini b/tests/wpt/mozilla/meta/mozilla/enabled_disabled_selectors.html.ini new file mode 100644 index 00000000000..f8b54e6eb73 --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/enabled_disabled_selectors.html.ini @@ -0,0 +1,5 @@ +[enabled_disabled_selectors.html] + type: testharness + [menuitem initial state] + expected: FAIL + diff --git a/tests/wpt/mozilla/meta/mozilla/windowproxy.html.ini b/tests/wpt/mozilla/meta/mozilla/windowproxy.html.ini new file mode 100644 index 00000000000..ef3f60406f0 --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/windowproxy.html.ini @@ -0,0 +1,5 @@ +[windowproxy.html] + type: testharness + [Unforgeable location] + expected: FAIL + diff --git a/tests/wpt/mozilla/tests/css/class-namespaces-ref.html b/tests/wpt/mozilla/tests/css/class-namespaces-ref.html new file mode 100644 index 00000000000..96c68eff366 --- /dev/null +++ b/tests/wpt/mozilla/tests/css/class-namespaces-ref.html @@ -0,0 +1,5 @@ +<style> +p { background: green; } +</style> +<body> +<p>AAA</p><p>BBB</p> diff --git a/tests/wpt/mozilla/tests/css/class-namespaces.html b/tests/wpt/mozilla/tests/css/class-namespaces.html new file mode 100644 index 00000000000..239d1629fc3 --- /dev/null +++ b/tests/wpt/mozilla/tests/css/class-namespaces.html @@ -0,0 +1,16 @@ +<link rel=match href=class-namespaces-ref.html> +<style> +.foo { background: green; } +</style> +<body> +<script> +var p = document.body.appendChild(document.createElement("p")); +p.setAttributeNS("foo", "class", "bar"); +p.setAttributeNS("", "class", "foo"); +p.textContent = "AAA"; + +var p = document.body.appendChild(document.createElement("p")); +p.setAttributeNS("", "class", "foo"); +p.setAttributeNS("foo", "class", "bar"); +p.textContent = "BBB"; +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/DOMParser.html b/tests/wpt/mozilla/tests/mozilla/DOMParser.html new file mode 100644 index 00000000000..f78eccb4e36 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/DOMParser.html @@ -0,0 +1,14 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(String(DOMParser).indexOf("function DOMParser("), 0); + let parser = new DOMParser(); + assert_true(parser instanceof DOMParser, "Should be DOMParser"); + assert_true(parser.parseFromString("", "text/html") instanceof Document, "Should be Document"); +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/Event.html b/tests/wpt/mozilla/tests/mozilla/Event.html new file mode 100644 index 00000000000..94e72dba2df --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/Event.html @@ -0,0 +1,19 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(String(Event).indexOf("function Event("), 0); + + let ev = new Event("foopy", {cancelable: true}); + assert_true(ev instanceof Event, "Should be Event"); + + assert_equals(ev.type, 'foopy'); + assert_equals(ev.defaultPrevented, false); + ev.preventDefault(); + assert_equals(ev.defaultPrevented, true); +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/MouseEvent.html b/tests/wpt/mozilla/tests/mozilla/MouseEvent.html new file mode 100644 index 00000000000..3456da1f28e --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/MouseEvent.html @@ -0,0 +1,19 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(String(MouseEvent).indexOf("function MouseEvent("), 0); + + let ev = new MouseEvent("press", {bubbles: true, screenX: 150, detail: 100}); + + assert_true(ev instanceof Event, "Should be Event"); + assert_true(ev instanceof UIEvent, "Should be UIEvent"); + assert_true(ev instanceof MouseEvent, "Should be MouseEvent"); + assert_equals(ev.screenX, 150); + assert_equals(ev.detail, 100); +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/blob.html b/tests/wpt/mozilla/tests/mozilla/blob.html new file mode 100644 index 00000000000..3f932083542 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/blob.html @@ -0,0 +1,46 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + var testData = ['<a id="a"><b id="b">hey!</b></a>']; + var b = new Blob(testData); // the blob + assert_equals(b.size, 32); + assert_equals(b.type, ""); + + var bs = b.slice(0, 5); + assert_equals(bs.size, 5); + assert_equals(b.type, ""); + + var bc = new Blob(testData, {type:"text/plain"}); // the blob + assert_equals(bc.size, 32); + assert_equals(bc.type, "text/plain"); + + var bss = new Blob(testData, {type:" text/plain "}); // spaces + assert_equals(bss.size, 32); + assert_equals(bss.type, " text/plain "); + + var bcs = bc.slice(0, 7); + assert_equals(bcs.size, 7); + assert_equals(bcs.type, ""); + + var bcsc = bc.slice(0, 7, "text/xml"); + assert_equals(bcsc.size, 7); + assert_equals(bcsc.type, "text/xml"); + + var bu = new Blob(testData, {type:"TEXT/PLAIN"}); // the blob + assert_equals(bu.size, 32); + assert_equals(bu.type, "text/plain"); + + var bj = new Blob(testData, {type:"☃"}); // the blob + assert_equals(bj.size, 32); + assert_equals(bj.type, ""); + + var bjs = bj.slice(0, 7, "☃"); + assert_equals(bjs.size, 7); + assert_equals(bjs.type, ""); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/body_listener.html b/tests/wpt/mozilla/tests/mozilla/body_listener.html new file mode 100644 index 00000000000..13a1a0fdc15 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/body_listener.html @@ -0,0 +1,20 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +async_test(function() { + window.check_onload = this.step_func(function(listener) { + assert_equals(listener, window); + var ev = new Event('click', {bubbles: true, cancelable: true}); + document.body.dispatchEvent(ev); + }); + window.check_onclick = this.step_func_done(function(listener) { + assert_equals(listener, document.body); + }); +}); +</script> +</head> +<body onload="check_onload(this)" onclick="check_onclick(this)"> +</body> +</html> diff --git a/tests/content/test_caption.html b/tests/wpt/mozilla/tests/mozilla/caption.html index 64d487df922..85f31176e32 100644 --- a/tests/content/test_caption.html +++ b/tests/wpt/mozilla/tests/mozilla/caption.html @@ -1,24 +1,27 @@ <html> <head> -<script src="harness.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> </head> <table id="t"> <caption id="tcaption">old caption</caption> </table> <script> +test(function() { var t = document.getElementById("t"); var tcaption = document.getElementById("tcaption"); - is(t.caption, tcaption); - is(t.caption.innerHTML, "old caption"); + assert_equals(t.caption, tcaption); + assert_equals(t.caption.innerHTML, "old caption"); var newCaption = document.createElement("caption"); newCaption.innerHTML = "new caption"; t.caption = newCaption; - is(newCaption.parentNode, t); - is(t.caption, newCaption); + assert_equals(newCaption.parentNode, t); + assert_equals(t.caption, newCaption); // Test for https://github.com/servo/servo/issues/3997 t.getBoundingClientRect(); +}); </script> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/characterdata.html b/tests/wpt/mozilla/tests/mozilla/characterdata.html new file mode 100644 index 00000000000..fe2dafa8675 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/characterdata.html @@ -0,0 +1,47 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <p>This is the character data</p> + </body> + <script> + test(function() { + var a = document.getElementsByTagName('p')[0].childNodes[0]; + assert_equals(a.data, "This is the character data"); + // append test utf8 + a.appendData(", append more 資料,測試資料"); + assert_equals(a.data, "This is the character data, append more 資料,測試資料"); + + // length test utf8 + assert_equals(a.length, 47); + + // insert test non-utf8 + a.insertData(26, " test"); + assert_equals(a.data, "This is the character data test, append more 資料,測試資料"); + // insert test utf8 + a.insertData(48, "更多"); + assert_equals(a.data, "This is the character data test, append more 資料,更多測試資料"); + + // delete test non-utf8 + a.deleteData(40, 5); + assert_equals(a.data, "This is the character data test, append 資料,更多測試資料"); + // delete test utf8 + a.deleteData(45, 2); + assert_equals(a.data, "This is the character data test, append 資料,更多資料"); + + // replace test non-utf8 + a.replaceData(33, 6, "other"); + assert_equals(a.data, "This is the character data test, other 資料,更多資料"); + // replace test non-utf8 + a.replaceData(44, 2, "文字"); + assert_equals(a.data, "This is the character data test, other 資料,更多文字"); + + // substring test non-utf8 + assert_equals(a.substringData(12, 4), "char"); + // substring test utf8 + assert_equals(a.substringData(39, 2), "資料"); + }); + </script> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/click_prevent.html b/tests/wpt/mozilla/tests/mozilla/click_prevent.html new file mode 100644 index 00000000000..c330e7339e4 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/click_prevent.html @@ -0,0 +1,17 @@ +<html> +<head> +<script src="./harness.js"></script> +<a id="foo" href="/nonexistent">test link</a> +<script> +async_test(function() { + var link = document.getElementById('foo'); + link.addEventListener('click', this.step_func(function(ev) { + ev.preventDefault(); + })); + var ev = new Event('click', {bubbles: true, cancelable: true}); + link.dispatchEvent(ev); + setTimeout(this.step_func_done(), 500); +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/collections.html b/tests/wpt/mozilla/tests/mozilla/collections.html new file mode 100644 index 00000000000..2f33466cfa8 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/collections.html @@ -0,0 +1,149 @@ +<html> +<head> +<meta charset="utf-8"> +<title>test_binding + page </title> +<base href="./"></base> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> + +<div id="first" name="test">fffff<br><br><br><br>fffffffffffffffff</div> +<div id="second">ggg</div> +<span id="third" name="test">hhhhhhhh</span> +<div id="fourth">iiiiiiiiiiiiiiiiiii</div> +<a href="http://www.mozilla.org"></a> +<img src="test.jpg"/> +<embed></embed> +<form> + <fieldset> + <legend>legend</legend> + <label for="">label<input type="text" value="input" /></label> + </fieldset> +</form> +<hr /> +<canvas/> +<p>pppppppppp</p> +<q>qqqqqqqqqqqqqqqqqqqqqqqqqqq</q> +<progress max="100" value="80">80%</progress> +<applet></applet> +<input type="text" value="input"/> +<iframe></iframe> +<ol type="1"> + <li>li</li> +</ol> +<table> + <caption>sample table</caption> + <colgroup> + <col/> + </colgroup> + <tbody> + <tr><th>head</th></tr> + <tr><td>data</td></tr> + </tbody> +</table> +<section>section</section> +<aside>aside</aside> +<b>b</b> +<i>i</i> +<small>small</small> +<textarea>textarea</textarea> +<time datetime="2014-02-14">Valentines day</time> +<area></area> +<data></data> +<dialog></dialog> +<template></template> +<pre>pre</pre> +<audio> + <source src="horse.ogg" type="audio/ogg"> + <source src="horse.mp3" type="audio/mpeg"> +</audio> +<video src=""> + <track></track> +</video> + +<foo-á>hi</foo-á> + +<script> +test(function() { + function check_collection(obj, num, classes, name) { + test(function() { + assert_true(obj instanceof HTMLCollection, "Should be HTMLCollection"); + assert_equals(obj.length, num); + assert_equals(obj[obj.length], undefined); + + if (classes === undefined) { + return; + } + + classes = [Element, HTMLElement].concat(classes); + + for (var i = 0; i < obj.length; i++) { + assert_not_equals(obj[i], undefined); + assert_equals(obj[i].tagName, name); + for (var j = 0; j < classes.length; j++) { + assert_true(obj[i] instanceof classes[j], "Should be " + classes[j]); + } + } + }); + } + + function check_tag(tagname, num, classes, tagname_upper) { + if (tagname_upper === undefined) + tagname_upper = tagname.toUpperCase(); + check_collection(document.getElementsByTagName(tagname), num, classes, tagname_upper); + } + + check_collection(document.links, 1, [HTMLAnchorElement], "A"); + check_collection(document.images, 1, [HTMLImageElement], "IMG"); + check_collection(document.embeds, 1, [HTMLEmbedElement], "EMBED"); + check_collection(document.plugins, 1, [HTMLEmbedElement], "EMBED"); + check_collection(document.scripts, 3, [HTMLScriptElement], "SCRIPT"); + check_collection(document.applets, 1, [HTMLAppletElement], "APPLET"); + check_collection(document.forms, 1, [HTMLFormElement], "FORM"); + + check_collection(document.getElementsByTagName("nosuchtag"), 0); + + check_tag("section", 1, []); + check_tag("aside", 1, []); + check_tag("b", 1, []); + check_tag("i", 1, []); + check_tag("small", 1, []); + check_tag("head", 1, [HTMLHeadElement]); + check_tag("div", 3, [HTMLDivElement]); + check_tag("iframe", 1, [HTMLIFrameElement]); + check_tag("body", 1, [HTMLBodyElement]); + check_tag("area", 1, [HTMLAreaElement]); + check_tag("base", 1, [HTMLBaseElement]); + check_tag("data", 1, [HTMLDataElement]); + check_tag("dialog", 1, [HTMLDialogElement]); + check_tag("ol", 1, [HTMLOListElement]); + check_tag("canvas", 1, [HTMLCanvasElement]); + check_tag("source", 2, [HTMLSourceElement]); + check_tag("time", 1, [HTMLTimeElement]); + check_tag("caption", 1, [HTMLTableCaptionElement]); + check_tag("textarea", 1, [HTMLTextAreaElement]); + check_tag("q", 1, [HTMLQuoteElement]); + check_tag("th", 1, [HTMLTableCellElement, HTMLTableHeaderCellElement]); + check_tag("td", 1, [HTMLTableCellElement, HTMLTableDataCellElement]); + check_tag("col", 1, [HTMLTableColElement]); + check_tag("colgroup", 1, [HTMLTableColElement]); + check_tag("input", 2, [HTMLInputElement]); + check_tag("li", 1, [HTMLLIElement]); + check_tag("progress", 1, [HTMLProgressElement]); + check_tag("template", 1, [HTMLTemplateElement]); + check_tag("pre", 1, [HTMLPreElement]); + check_tag("legend", 1, [HTMLLegendElement]); + check_tag("label", 1, [HTMLLabelElement]); + check_tag("track", 1, [HTMLTrackElement]); + check_tag("audio", 1, [HTMLMediaElement, HTMLAudioElement]); + check_tag("video", 1, [HTMLMediaElement, HTMLVideoElement]); + + // Test non-ASCII tag names. Uppercasing is ASCII-only per spec: + // http://dom.spec.whatwg.org/#dom-element-tagname + check_tag("foo-á", 1, [HTMLUnknownElement], "FOO-á"); +}); +</script> +</body> +</html> diff --git a/tests/content/test_createElement_script.html b/tests/wpt/mozilla/tests/mozilla/createElement_script.html index ec5b2d01dd0..df819e861d9 100644 --- a/tests/content/test_createElement_script.html +++ b/tests/wpt/mozilla/tests/mozilla/createElement_script.html @@ -1,11 +1,14 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <script> - var output = "start"; + var output; + test(function() { + output = "start"; var script = document.createElement("script"); script.setAttribute('type','text/javascript'); @@ -13,7 +16,8 @@ document.body.appendChild(script); output += "end"; - is(output, "start middle end"); + assert_equals(output, "start middle end"); + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/create_element.html b/tests/wpt/mozilla/tests/mozilla/create_element.html new file mode 100644 index 00000000000..0ceeae5de98 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/create_element.html @@ -0,0 +1,21 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <script> + test(function() { + var elem = document.createElement("foo"); + assert_equals(elem.tagName, "FOO"); + var elem = document.createElement("p"); + assert_true(elem instanceof HTMLParagraphElement, "Should be HTMLParagraphElement"); + var elem = document.createElement("sPAn"); + assert_true(elem instanceof HTMLSpanElement, "Should be HTMLSpanElement"); + var text = document.createTextNode("hello"); + assert_true(text instanceof Text, "Should be Text"); + }); + </script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/documentElement.html b/tests/wpt/mozilla/tests/mozilla/documentElement.html new file mode 100644 index 00000000000..aee3278ba84 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/documentElement.html @@ -0,0 +1,15 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_true(window instanceof Window, "Should be Window"); + assert_true(document.documentElement instanceof HTMLHtmlElement, "Should be HTMLHtmlElement"); + assert_true(document.documentElement.firstChild instanceof HTMLHeadElement, "Should be HTMLHeadElement"); + assert_equals(document.documentElement.nextSibling, null); + assert_true(document instanceof Document, "Should be Document"); +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_activeElement.html b/tests/wpt/mozilla/tests/mozilla/document_activeElement.html new file mode 100644 index 00000000000..92a8e399adb --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_activeElement.html @@ -0,0 +1,21 @@ +<!doctype html> +<html> + <head > + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <input id="foo" type="text"></input> + <script> + test(function() { + assert_not_equals(document.activeElement, null, "test_1.1, document.activeElement"); + assert_equals(document.activeElement, document.body, "test_1.2, document.activeElement"); + + document.getElementById('foo').focus(); + assert_not_equals(document.activeElement, null, "test_2.1, document.activeElement"); + assert_equals(document.activeElement, document.getElementById("foo"), "test_2.2, document.activeElement"); + }); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_body.html b/tests/wpt/mozilla/tests/mozilla/document_body.html new file mode 100644 index 00000000000..526794a4ca9 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_body.html @@ -0,0 +1,66 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + test(function() { + assert_not_equals(document.body, null, "test1-0, existing document's body"); + assert_true(document.body instanceof HTMLBodyElement, "test1-1, exising document's body: should be HTMLBodyElement"); + assert_equals(document.body && document.body.tagName, "BODY", "test1-2, existing document's body"); + }, "existing document's body"); + + test(function() { + let new_body = document.createElement("body"); + assert_not_equals(new_body, null, "test2-0, replace document's body with new body"); + document.body = new_body; + assert_equals(new_body, document.body, "test2-1, replace document's body with new body"); + }, "replace document's body with new body"); + + test(function() { + let new_frameset = document.createElement("frameset"); + assert_not_equals(new_frameset, null, "test2-0, replace document's body with new frameset"); + document.body = new_frameset; + assert_equals(new_frameset, document.body, "test2-1, replace document's body with new frameset"); + }, "replace document's body with new frameset"); + + test(function() { + let new_document = new Document(); + new_document.appendChild(new_document.createElement("html")); + let new_div = new_document.createElement("div"); + + assert_not_equals(new_div, null, "test4-0, append an invalid element to a new document"); + + assert_throws(null, function() { + new_document.body = new_div; + }); + assert_equals(new_document.body, null, "test4-1, append an invalid element to a new document"); + }, "append an invalid element to a new document"); + + test(function() { + let new_document = document.implementation.createHTMLDocument(); + let new_body = new_document.createElement("body"); + + assert_not_equals(new_body, null, "test5-0, append body to a new document"); + assert_true(new_body instanceof HTMLBodyElement, "test5-1, append body to a new document: should be HTMLBodyElement"); + assert_equals(new_body && new_body.tagName, "BODY", "test5-2, append body to a new document"); + + new_document.body = new_body; + assert_equals(new_document.body, new_body, "test5-3, append body to a new document"); + }, "append body to a new document"); + + test(function() { + let new_document = document.implementation.createHTMLDocument(); + let new_frameset = new_document.createElement("frameset"); + + assert_not_equals(new_frameset, null, "test6-0, append frameset to a new document"); + assert_true(new_frameset instanceof HTMLFrameSetElement, "test6-1, append frameset to a new document: should be HTMLFrameSetElement"); + assert_equals(new_frameset && new_frameset.tagName, "FRAMESET", "test6-2, append frameset to a new document"); + + new_document.body = new_frameset; + assert_equals(new_document.body, new_frameset, "test6-3, append frameset to a new document"); + }, "append frameset to a new document"); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_characterSet.html b/tests/wpt/mozilla/tests/mozilla/document_characterSet.html new file mode 100644 index 00000000000..70d892aae56 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_characterSet.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_equals(document.characterSet, "UTF-8", "test1-0, characterSet"); + + var xmldoc = new Document; + assert_equals(xmldoc.characterSet, "UTF-8", "test2-1, characterSet"); + + var htmldoc = document.implementation.createHTMLDocument("title"); + assert_equals(htmldoc.characterSet, "UTF-8", "test2-2, characterSet"); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_characterSet_default.html b/tests/wpt/mozilla/tests/mozilla/document_characterSet_default.html new file mode 100644 index 00000000000..5dbd445b67b --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_characterSet_default.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_equals(document.characterSet, "UTF-8", "test1-0, default characterSet"); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_characterSet_invalid.html b/tests/wpt/mozilla/tests/mozilla/document_characterSet_invalid.html new file mode 100644 index 00000000000..129fbe0a389 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_characterSet_invalid.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<meta charset="unknown-charset"> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_equals(document.characterSet, "UTF-8", "test1-0, unknown charset"); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_characterSet_long.html b/tests/wpt/mozilla/tests/mozilla/document_characterSet_long.html new file mode 100644 index 00000000000..c420ced2770 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_characterSet_long.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(document.characterSet, "windows-1252"); +}); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/document_characterSet_short.html b/tests/wpt/mozilla/tests/mozilla/document_characterSet_short.html new file mode 100644 index 00000000000..c36b81d3fbe --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_characterSet_short.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<meta charset="iso-8859-1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(document.characterSet, "windows-1252"); +}); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/document_compatMode_loose.html b/tests/wpt/mozilla/tests/mozilla/document_compatMode_loose.html new file mode 100644 index 00000000000..b1bf75b1e7f --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_compatMode_loose.html @@ -0,0 +1,12 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_equals(document.compatMode, "BackCompat", "test1-0, Loose HTML"); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_compatMode_strict.html b/tests/wpt/mozilla/tests/mozilla/document_compatMode_strict.html new file mode 100644 index 00000000000..39ecdc22bab --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_compatMode_strict.html @@ -0,0 +1,12 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_equals(document.compatMode, "CSS1Compat", "test1-0, Strict HTML"); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_contenttype.html b/tests/wpt/mozilla/tests/mozilla/document_contenttype.html new file mode 100644 index 00000000000..efa63b2ea39 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_contenttype.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_true(document instanceof Document, "test1-0, HTML document: should be Document"); + assert_equals(document.contentType, "text/html", "test1-1, HTML document"); + }, "HTML document"); + + test(function() { + var doc = new Document; + assert_true(doc instanceof Document, "test2-0, XML document: should be Document"); + assert_equals(doc.contentType, "application/xml", "test2-1, XML document"); + }, "XML document"); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_datalist_options.html b/tests/wpt/mozilla/tests/mozilla/document_datalist_options.html new file mode 100644 index 00000000000..28441f21ed5 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_datalist_options.html @@ -0,0 +1,22 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <datalist id="id"> + <option value="A"> + <option value="B"> + <p>P</p> + <div>DIV</div> + <option value="C"> + </datalist> + <script> + test(function() { + var datalist = document.getElementById("id"); + assert_equals(datalist.options.length, 3); + assert_true(datalist.options[0] instanceof HTMLOptionElement, "Should be HTMLOptionElement"); + assert_true(datalist.options[1] instanceof HTMLOptionElement, "Should be HTMLOptionElement"); + assert_true(datalist.options[2] instanceof HTMLOptionElement, "Should be HTMLOptionElement"); + }); + </script> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_defaultView.html b/tests/wpt/mozilla/tests/mozilla/document_defaultView.html new file mode 100644 index 00000000000..cd99a11bae9 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_defaultView.html @@ -0,0 +1,13 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + test(function() { + assert_equals(document.defaultView, window); + }); + </script> + </body> +</html> diff --git a/tests/content/test_document_getElementById.html b/tests/wpt/mozilla/tests/mozilla/document_getElementById.html index 7484fdf4eb5..4a22528c88f 100644 --- a/tests/content/test_document_getElementById.html +++ b/tests/wpt/mozilla/tests/mozilla/document_getElementById.html @@ -1,11 +1,13 @@ <html> <head id="foo"> <title></title> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <div id="bar"></div> <script> + test(function() { let gBody = document.getElementsByTagName("body")[0]; // Test the assertion with inserting node with child having id into the document (mozilla#2630) @@ -17,8 +19,9 @@ a.appendChild(b).id = TEST_ID; gBody.appendChild(a); let result = document.getElementById(TEST_ID); - is(result, b, "test 9-0"); + assert_equals(result, b, "test 9-0"); } + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_getElementsByName.html b/tests/wpt/mozilla/tests/mozilla/document_getElementsByName.html new file mode 100644 index 00000000000..07c79725c4d --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_getElementsByName.html @@ -0,0 +1,17 @@ +<html> +<head > + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div name="foo"></div> + <script> + test(function() { + let nameList = document.getElementsByName("foo"); + assert_true(nameList instanceof NodeList, "Should be NodeList"); + assert_false(nameList instanceof HTMLCollection, "Should not be HTMLCollection"); + }); + </script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_head.html b/tests/wpt/mozilla/tests/mozilla/document_head.html new file mode 100644 index 00000000000..9070609d12c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_head.html @@ -0,0 +1,43 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + test(function() { + assert_not_equals(document.head, null, "test1-0, existing document's head"); + assert_true(document.head instanceof HTMLHeadElement, "test1-1, exising document's head: should be HTMLHeadElement"); + assert_equals(document.head && document.head.tagName, "HEAD", "test1-2, existing document's head"); + }, "existing document's head"); + + test(function() { + let new_document = new Document(); + new_document.appendChild(new_document.createElement("html")); + let new_head = new_document.createElement("head"); + + assert_not_equals(new_head, null, "test2-0, append head to a new document"); + assert_true(new_head instanceof HTMLHeadElement, "test2-1, append head to a new document: should be HTMLHeadElement"); + assert_equals(new_head && new_head.tagName, "head", "test2-2, append head to a new document"); + + // Document::head is read-only. + new_document.head = new_head; + assert_equals(new_document.head, null, "test2-3, append head to a new document"); + + new_document.documentElement.appendChild(new_head); + assert_equals(new_document.head, new_head, "test2-4, append head to a new document"); + }, "append head to a new document"); + + test(function() { + let new_document = new Document(); + let html = new_document.createElement("html"); + let foo = new_document.createElement("foo"); + let head = new_document.createElement("head"); + new_document.appendChild(html); + html.appendChild(foo); + foo.appendChild(head); + assert_equals(new_document.head, null, "test3-0, head's parent should be document element"); + }, "head's parent should be document element"); + </script> + </body> +</html> diff --git a/tests/content/test_document_images_cache.html b/tests/wpt/mozilla/tests/mozilla/document_images_cache.html index 9cc990b9e89..b1e4768c9e5 100644 --- a/tests/content/test_document_images_cache.html +++ b/tests/wpt/mozilla/tests/mozilla/document_images_cache.html @@ -1,7 +1,8 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> @@ -12,17 +13,19 @@ </noscript> <script> + test(function() { var images = document.images; - is(images, document.images); - is(images.length, 1); + assert_equals(images, document.images); + assert_equals(images.length, 1); var image = document.createElement("img"); image.setAttribute("src", "test.jpg"); document.body.appendChild(image); - is(images.length, 2); + assert_equals(images.length, 2); document.body.removeChild(image); - is(images.length, 1); + assert_equals(images.length, 1); + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_implementation.html b/tests/wpt/mozilla/tests/mozilla/document_implementation.html new file mode 100644 index 00000000000..e8652d90f56 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_implementation.html @@ -0,0 +1,76 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_not_equals(document.implementation, null, "test1-0, basic test"); + assert_true(document.implementation instanceof DOMImplementation, "test1-1, basic test: should be DOMImplementation"); + + var implementation = document.implementation; + assert_equals(document.implementation, implementation, "test1-2, basic test"); + }, "basic test"); + + test(function() { + assert_equals(document.doctype, null, "test2-0, createDocumentType"); + + var doctype = document.implementation.createDocumentType("html", null, null); + assert_true(doctype && doctype instanceof DocumentType, "test2-1, createDocumentType: should be DocumentType"); + + doctype = document.implementation.createDocumentType("html:html", null, null); + assert_true(doctype && doctype instanceof DocumentType, "test2-2, createDocumentType: should be DocumentType"); + }, "createDocumentType"); + + test(function() { + var htmldoc = document.implementation.createHTMLDocument("example title"); + assert_not_equals(htmldoc, null, "test3-0, createHTMLDocument"); + assert_true(htmldoc instanceof Document, "test3-1, createHTMLDocument: should be Document"); + assert_equals(htmldoc.childNodes.length, 2, "test3-3, createHTMLDocument"); + + assert_true(htmldoc.doctype && htmldoc.doctype instanceof DocumentType, "test3-4, createHTMLDocument: should be DocumentType"); + assert_equals(htmldoc.doctype.name, "html", "test3-5, createHTMLDocument"); + + assert_true(htmldoc.documentElement && htmldoc.documentElement instanceof HTMLHtmlElement, "test3-6, createHTMLDocument: should be HTMLHtmlElement"); + assert_equals(htmldoc.documentElement.childNodes.length, 2, "test3-7, createHTMLDocument"); + assert_equals(htmldoc.documentElement.tagName, "HTML", "test3-8, createHTMLDocument"); + + assert_true(htmldoc.head && htmldoc.head instanceof HTMLHeadElement, "test3-9, createHTMLDocument: should be HTMLHeadElement"); + assert_equals(htmldoc.head.tagName, "HEAD", "test3-10, createHTMLDocument"); + assert_equals(htmldoc.head, htmldoc.documentElement.childNodes[0], "test3-11, createHTMLDocument"); + assert_equals(htmldoc.head.childNodes.length, 1, "test3-12, createHTMLDocument"); + + assert_true(htmldoc.head.childNodes[0] instanceof HTMLTitleElement, "test3-13, createHTMLDocument: should be HTMLTitleElement"); + assert_equals(htmldoc.head.childNodes[0].tagName, "TITLE", "test3-14, createHTMLDocument"); + assert_equals(htmldoc.title, "example title", "test3-15, createHTMLDocument"); + + assert_true(htmldoc.body && htmldoc.body instanceof HTMLBodyElement, "test3-16, createHTMLDocument: should be HTMLBodyElement"); + assert_equals(htmldoc.body.tagName, "BODY", "test3-17, createHTMLDocument"); + assert_equals(htmldoc.body, htmldoc.documentElement.childNodes[1], "test3-18, createHTMLDocument"); + assert_equals(htmldoc.body.childNodes.length, 0, "test3-19, createHTMLDocument"); + }, "createHTMLDocument"); + + test(function() { + var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null); + assert_not_equals(doc, null, "test4-0, createDocument"); + assert_true(doc instanceof Document, "test4-1, createDocument: should be Document"); + assert_equals(doc.childNodes.length, 1, "test4-2, createDocument"); + assert_equals(doc.doctype, null, "test4-3, createDocument"); + assert_true(doc.documentElement instanceof HTMLHtmlElement, "test4-4, createDocument: should be HTMLHtmlElement"); + + var doctype = document.implementation.createDocumentType("html", null, null); + doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', doctype); + assert_equals(doc.childNodes.length, 2, "test4-5, createDocument"); + assert_equals(doc.doctype, doctype, "test4-6, createDocument"); + assert_true(doc.documentElement instanceof HTMLHtmlElement, "test4-7, createDocument: should be HTMLHtmlElement"); + + doctype = document.implementation.createDocumentType( + 'svg:svg', '-//W3C//DTD SVG 1.1//EN', + 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'); + doc = document.implementation.createDocument('http://www.w3.org/2000/svg', 'svg:svg', doctype); + assert_equals(doc.childNodes.length, 2, "test4-8, createDocument"); + assert_equals(doc.doctype, doctype, "test4-9, createDocument"); + assert_true(doc.documentElement instanceof Element, "test4-10, createDocument: should be Element"); + }, "createDocument"); + </script> + </head> +</html> diff --git a/tests/content/test_document_links_cache.html b/tests/wpt/mozilla/tests/mozilla/document_links_cache.html index 590939e42f7..3a0172826d4 100644 --- a/tests/content/test_document_links_cache.html +++ b/tests/wpt/mozilla/tests/mozilla/document_links_cache.html @@ -1,37 +1,40 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <script> + test(function() { var links = document.links; - is(links, document.links); - is(links.length, 0); + assert_equals(links, document.links); + assert_equals(links.length, 0); var anchor = document.createElement("a"); anchor.id = "anchor-with-href"; anchor.setAttribute("href", "http://www.google.com"); document.body.appendChild(anchor); - is(links.length, 1); + assert_equals(links.length, 1); anchor = document.createElement("a"); anchor.id = "anchor-without-href"; document.body.appendChild(anchor); - is(links.length, 1); + assert_equals(links.length, 1); anchor.setAttribute("href", "http://www.google.com"); - is(links.length, 2); + assert_equals(links.length, 2); anchor.removeAttribute("href", "http://www.google.com"); - is(links.length, 1); + assert_equals(links.length, 1); document.body.removeChild(document.getElementById("anchor-without-href")); - is(links.length, 1); + assert_equals(links.length, 1); document.body.removeChild(document.getElementById("anchor-with-href")); - is(links, document.links); - is(links.length, 0); + assert_equals(links, document.links); + assert_equals(links.length, 0); + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_readystate.html b/tests/wpt/mozilla/tests/mozilla/document_readystate.html new file mode 100644 index 00000000000..7ff8f66cdf7 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_readystate.html @@ -0,0 +1,21 @@ +<html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <script> + async_test(function() { + var numChanges = 0; + document.addEventListener('readystatechange', this.step_func(function() { + numChanges++; + }), true); + window.onload = this.step_func_done(function() { + assert_equals(document.readyState, 'complete'); + assert_equals(numChanges, 2); + }); + assert_equals(document.readyState, "loading"); + }); + </script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_set_node_value.html b/tests/wpt/mozilla/tests/mozilla/document_set_node_value.html new file mode 100644 index 00000000000..c6e23b8a055 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_set_node_value.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <body> + <div id="div" class="div-class">A</div> + <p>P</p> + <script> + test(function() { + assert_equals(document.nodeValue, null); + var div = document.getElementById("div"); + assert_equals(div.nodeValue, null); + assert_equals(div.firstChild.nodeValue, "A"); + div.firstChild.nodeValue = "B"; + assert_equals(div.firstChild.nodeValue, "B"); + var commentNode = document.createComment("comment node"); + assert_equals(commentNode.nodeValue, "comment node"); + }); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_title_nontextchildren.html b/tests/wpt/mozilla/tests/mozilla/document_title_nontextchildren.html new file mode 100644 index 00000000000..3f132f9ac1a --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_title_nontextchildren.html @@ -0,0 +1,11 @@ +<html> +<title>x</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + document.head.firstChild.appendChild(document.createElement("foo")); + assert_equals(document.title, "x"); +}); +</script> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/document_url.html b/tests/wpt/mozilla/tests/mozilla/document_url.html new file mode 100644 index 00000000000..e1c90d1bcd0 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/document_url.html @@ -0,0 +1,28 @@ +<!doctype html> +<html> + <head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + assert_not_equals(document.URL, null, "test1-0, URL & documentURI"); + assert_not_equals(document.documentURI, null, "test1-1, URL & documentURI"); + assert_equals(document.URL, document.documentURI, "test1-2, URL & documentURI"); + }, "URL & documentURI"); + + test(function() { + var doc = new Document(); + assert_equals(doc.URL, "about:blank", "test2-0, new document"); + }, "new document"); + + test(function() { + var url = document.URL.split("/"); + assert_equals(url[0], "http:", "test3-0, current document"); + assert_equals(url[url.length-1], "document_url.html", "test3-1, current document"); + }, "current document"); + </script> + </head> + <body> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/domtokenlist.html b/tests/wpt/mozilla/tests/mozilla/domtokenlist.html new file mode 100644 index 00000000000..a758d566e3e --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/domtokenlist.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + var div = document.createElement("div"); + var classList = div.classList; + + assert_equals(classList.length, 0); + assert_equals(classList.item(0), null); + assert_throws(null, function () { + classList.contains(""); + }); + assert_throws(null, function () { + classList.contains(" "); + }); + + var list = ["foo", " foo", "foo ", " foo ", " foo "]; + for(var i = 0; i < list.length; i++) { + div.className = list[i]; + assert_equals(div.className, list[i]); + assert_equals(classList.length, 1); + assert_equals(classList.item(0), "foo"); + assert_equals(classList.item(1), null); + assert_equals(classList.contains("foo"), true); + assert_equals(classList.contains("bar"), false); + } + + list = ["foo bar", " foo bar", " foo bar ", " foo bar "]; + for(var i = 0; i < list.length; i++) { + div.className = list[i]; + assert_equals(div.className, list[i]); + assert_equals(classList.length, 2); + assert_equals(classList.item(0), "foo"); + assert_equals(classList.item(1), "bar"); + assert_equals(classList.item(2), null); + assert_equals(classList.contains("foo"), true); + assert_equals(classList.contains("bar"), true); + assert_equals(classList.contains("baz"), false); + } + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/element_attribute.html b/tests/wpt/mozilla/tests/mozilla/element_attribute.html new file mode 100644 index 00000000000..a18ec78511a --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/element_attribute.html @@ -0,0 +1,67 @@ +<html> +<head id="foo"> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="test" foo="bar"></div> + <script> + let element = document.getElementById("test"); + + test(function() { + let r1 = element.getAttribute("id"); + assert_equals(r1, "test", "test1-0, Element.getAttribute()."); + let r2 = element.getAttribute("foo"); + assert_equals(r2, "bar", "test1-1, Element.getAttribute()."); + }); + + test(function() { + let NAME = "hoge"; + let VALUE = "fuga"; + element.setAttribute(NAME, VALUE); + let r = element.getAttribute(NAME); + assert_equals(r, VALUE, "test2. Element.setAttribute()."); + }); + + test(function() { + let NAME = "foo"; + let VALUE = "mozilla"; + element.setAttribute(NAME, VALUE); + let r = element.getAttribute(NAME); + assert_equals(r, VALUE, "test3, attribute update by Element.setAttribute().") + }); + + test(function() { + element.setAttribute("id", "bar"); + element.removeAttribute("id"); + + let r1 = element.hasAttribute("id"); + assert_equals(r1, false, "test4-0, Element.removeAttribute()."); + let r2 = element.getAttribute("id"); + assert_equals(r2, null, "test4-1, Element.removeAttribute()."); + }); + + test(function() { + element.setAttribute("xml:lang", "en"); + + let r1 = element.hasAttribute("xml:lang"); + assert_equals(r1, true, "test5-0, Element.setAttribute('xml:lang')."); + let r2 = element.getAttribute("xml:lang"); + assert_not_equals(r2, null, "test5-1, Element.setAttribute('xml:lang')."); + }); + + test(function() { + assert_throws(null, function () { + element.setAttributeNS("http://example.com", "xmlns", "foo"); + }); + assert_throws(null, function () { + element.setAttributeNS("http://www.w3.org/2000/xmlns/", "attr", "value"); + }); + assert_throws(null, function () { + element.setAttributeNS("http://www.w3.org/2000/xmlns/", "prefix:attr", "value"); + }); + }); + </script> +</body> +</html> diff --git a/tests/content/test_element_attributes.html b/tests/wpt/mozilla/tests/mozilla/element_attributes.html index 7eb560ec258..6a45c5b4c6f 100644 --- a/tests/content/test_element_attributes.html +++ b/tests/wpt/mozilla/tests/mozilla/element_attributes.html @@ -1,20 +1,23 @@ <html> <head id="foo"> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <div></div> <script> +test(function() { var attrs = []; for (var i = 'a'.charCodeAt(0); i != 'z'.charCodeAt(0); i++) { document.getElementsByTagName('div')[0].setAttribute(String.fromCharCode(i), - i.toString()); + i.toString()); } var attributes = document.getElementsByTagName('div')[0].attributes; for (var i = 0; i < attributes.length; i++) { - is(attributes[i].name, String.fromCharCode(i + 'a'.charCodeAt(0))); - is(attributes[i].value, (i + 'a'.charCodeAt(0)).toString()); + assert_equals(attributes[i].name, String.fromCharCode(i + 'a'.charCodeAt(0))); + assert_equals(attributes[i].value, (i + 'a'.charCodeAt(0)).toString()); } +}); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/element_classList.html b/tests/wpt/mozilla/tests/mozilla/element_classList.html new file mode 100644 index 00000000000..45936b06490 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/element_classList.html @@ -0,0 +1,22 @@ +<!-- Remove this and update WPT metadata once DOMTokenList.toggle (#3138) is implemented. --> +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + let div = document.createElement("div"); + div.className = "foo bar"; + + let classList = div.classList; + div.className = ""; + + assert_equals(classList.item(0), null, "classList.item(0) must return null when all classes have been removed"); + assert_equals(classList[0], undefined, "classList[0] must be undefined when all classes have been removed"); + }); + </script> + </head> + <body> + </body> +</html> diff --git a/tests/content/test_element_className.html b/tests/wpt/mozilla/tests/mozilla/element_className.html index 298205c4681..ffce5c17607 100644 --- a/tests/content/test_element_className.html +++ b/tests/wpt/mozilla/tests/mozilla/element_className.html @@ -1,36 +1,39 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <div id="foo-1" class="foo"></div> <div id="foo-2" class="baz"></div> <script> + test(function() { let foo1 = document.getElementById("foo-1"); let foo2 = document.getElementById("foo-2"); foo1.className += " bar"; - is(foo1.className, "foo bar"); + assert_equals(foo1.className, "foo bar"); let foo3 = document.createElement("div"); foo3.id = "foo-3"; foo3.className = "foo"; document.body.appendChild(foo3); - is(foo3, document.getElementById("foo-3")); + assert_equals(foo3, document.getElementById("foo-3")); let collection = document.getElementsByClassName("foo"); - is(collection.length, 2); - is(collection[0].id, foo1.id); - is(collection[1].id, foo3.id); + assert_equals(collection.length, 2); + assert_equals(collection[0].id, foo1.id); + assert_equals(collection[1].id, foo3.id); collection = document.getElementsByClassName("bar"); - is(collection.length, 1); - is(collection[0].id, foo1.id); + assert_equals(collection.length, 1); + assert_equals(collection[0].id, foo1.id); collection = document.getElementsByClassName("baz"); - is(collection.length, 1); - is(collection[0].id, foo2.id); + assert_equals(collection.length, 1); + assert_equals(collection[0].id, foo2.id); + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/element_matches.html b/tests/wpt/mozilla/tests/mozilla/element_matches.html new file mode 100644 index 00000000000..5e3cc422386 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/element_matches.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="foo"></div> + + <script> + test(function() { + let test = document.getElementById("foo"); + + assert_equals(test.matches("#foo"), true, "test-1"); + assert_equals(test.matches("#not-foo"), false, "test-2"); + }); + </script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/empty_clientrect.html b/tests/wpt/mozilla/tests/mozilla/empty_clientrect.html new file mode 100644 index 00000000000..d1aa50b2238 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/empty_clientrect.html @@ -0,0 +1,20 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + var rect = window.document.head.getBoundingClientRect(); + var rects = window.document.head.getClientRects(); + assert_true(rect instanceof DOMRect, "Should be DOMRect"); + assert_equals(rect.top, 0); + assert_equals(rect.bottom, 0); + assert_equals(rect.left, 0); + assert_equals(rect.right, 0); + assert_equals(rect.width, 0); + assert_equals(rect.height, 0); + assert_equals(rects.length, 0); +}); +</script> +</head> +</html> diff --git a/tests/content/test_enabled_disabled_selectors.html b/tests/wpt/mozilla/tests/mozilla/enabled_disabled_selectors.html index 3a46183de29..75a7b1a22bc 100644 --- a/tests/content/test_enabled_disabled_selectors.html +++ b/tests/wpt/mozilla/tests/mozilla/enabled_disabled_selectors.html @@ -2,7 +2,8 @@ <html> <head> <title>Tests for :enabled and :disabled selectors</title> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <button id="button-1"></button> @@ -52,7 +53,16 @@ </legend> </fieldset> <script> - { // Simple initialization checks. + function check_selector(elem, selector, matches) { + assert_equals(elem.matches(selector), matches); + } + + function check_disabled_selector(elem, disabled) { + check_selector(elem, ":disabled", disabled); + check_selector(elem, ":enabled", !disabled); + } + + test(function() { var list, i, elem; // Examples of elements which are never :enabled or :disabled. @@ -73,15 +83,19 @@ } // These are :enabled (and not :disabled) by default. - // XXX: Add 'menuitem' here whenever available. list = ['button', 'input', 'select', 'textarea', 'optgroup', 'option', 'fieldset']; for(i = 0; i < list.length; i++) { elem = document.createElement(list[i]); check_disabled_selector(elem, false); } - } + }, "Simple initialization checks"); - { // Document elements tests. + test(function() { + var elem = document.createElement('menuitem'); + check_disabled_selector(elem, false); + }, "menuitem initial state"); + + test(function() { var click_count = 0; var click_event = new Event('click', {bubbles: true, cancelable: true}); var list, elem1, elem2, elem3, elem4, elem5; @@ -93,36 +107,36 @@ click_count = 0; elem1 = document.getElementById(list[i] + "-1"); - is(elem1.disabled, false); + assert_equals(elem1.disabled, false); elem1.addEventListener('click', on_click); elem1.dispatchEvent(click_event); - is(click_count, 1); + assert_equals(click_count, 1); elem2 = document.getElementById(list[i] + "-2"); - is(elem2.disabled, true); + assert_equals(elem2.disabled, true); // Only user-generated click events are prevented. elem2.addEventListener('click', on_click); elem2.dispatchEvent(click_event); - is(click_count, 2); + assert_equals(click_count, 2); // This should look disabled, though - missing UA's CSS for :disabled? elem3 = document.getElementById(list[i] + "-3"); - is(elem3.disabled, false); + assert_equals(elem3.disabled, false); if (list[i] == 'option') { continue; } elem4 = document.getElementById(list[i] + "-4"); - is(elem4.disabled, false); + assert_equals(elem4.disabled, false); // This should look disabled, though - missing UA's CSS for :disabled? elem5 = document.getElementById(list[i] + "-5"); - is(elem5.disabled, false); + assert_equals(elem5.disabled, false); } - } + }, "Document elements tests") - { // JS tests (Button, Input, Select, TextArea). + test(function() { var list = ['button', 'input', 'select', 'textarea']; var fieldset = document.createElement("fieldset"); fieldset.disabled = true; @@ -151,9 +165,9 @@ div.removeChild(elem); check_disabled_selector(elem, false); } - } + }, "JS tests (Button, Input, Select, TextArea)"); - { // JS tests (Option). + test(function() { var optgroup = document.createElement("optgroup"); optgroup.disabled = true; @@ -171,7 +185,7 @@ optgroup.removeChild(option); check_disabled_selector(option, false); - } + }, "JS tests (Option)"); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/event_dispatch.html b/tests/wpt/mozilla/tests/mozilla/event_dispatch.html new file mode 100644 index 00000000000..304b55fbeca --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/event_dispatch.html @@ -0,0 +1,52 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<span>Paragraph containing <div>event listener</div>.</span> +<script> +test(function() { + var bodyTimes = 0; + function bodyListener(ev) { + bodyTimes++; + assert_equals(ev.currentTarget, document.getElementsByTagName('body')[0]); + assert_equals(ev.target, document.getElementsByTagName('div')[0]); + if (bodyTimes == 1) { + assert_equals(ev.eventPhase, ev.CAPTURING_PHASE); + } else if (bodyTimes == 2) { + assert_equals(ev.eventPhase, ev.BUBBLING_PHASE); + } + } + + var spanTimes = 0; + function spanListener(ev) { + assert_equals(ev.currentTarget, document.getElementsByTagName('span')[0]); + assert_equals(ev.target, document.getElementsByTagName('div')[0]); + assert_equals(ev.eventPhase, ev.BUBBLING_PHASE); + spanTimes++; + } + + var divTimes = 0; + function divListener(ev) { + var self = document.getElementsByTagName('div')[0]; + assert_equals(ev.currentTarget, self); + assert_equals(ev.target, self); + assert_equals(ev.eventPhase, ev.AT_TARGET); + divTimes++; + } + + document.getElementsByTagName('body')[0].addEventListener("foopy", this.step_func(bodyListener), true); + document.getElementsByTagName('body')[0].addEventListener("foopy", this.step_func(bodyListener), false); + document.getElementsByTagName('span')[0].addEventListener("foopy", this.step_func(spanListener), false); + document.getElementsByTagName('div')[0].addEventListener("foopy", this.step_func(divListener), false); + var ev = new Event('foopy', {bubbles: true}); + assert_equals(ev.bubbles, true); + document.getElementsByTagName('div')[0].dispatchEvent(ev); + assert_equals(bodyTimes, 2, 'body listener should be called multiple times'); + assert_equals(divTimes, 1, 'target listener should be called once'); + assert_equals(spanTimes, 1, 'span listener should be called while bubbling'); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/event_dispatch_dynamic.html b/tests/wpt/mozilla/tests/mozilla/event_dispatch_dynamic.html new file mode 100644 index 00000000000..08dc4c89a6d --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/event_dispatch_dynamic.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<b><b><b></b></b></b> +<script> +test(function() { + var sawmiddle = -1; + var sawouter = -1; + var step = 0; + var outerb = document.getElementsByTagName('b')[0]; + var middleb = outerb.firstChild; + var innerb = middleb.firstChild; + outerb.addEventListener("x", this.step_func(function() { + middleb.addEventListener("x", this.step_func(function() { + sawmiddle = step++; + }), true); + sawouter = step++; + }), true); + innerb.dispatchEvent(new Event("x")); + assert_equals(sawmiddle, 1); + assert_equals(sawouter, 0); +}); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/event_dispatch_order.html b/tests/wpt/mozilla/tests/mozilla/event_dispatch_order.html new file mode 100644 index 00000000000..48513cfff42 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/event_dispatch_order.html @@ -0,0 +1,44 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="foo"></div> +<script> +test(function() { + var sawBubble = false; + var sawCapture = false; + var sawBubbleTwice = false; + function handler(ev) { + assert_equals(ev.eventPhase, ev.AT_TARGET); + assert_equals(sawBubble, false); + assert_equals(sawCapture, false); + sawBubble = true; + } + function handler2(ev) { + assert_equals(ev.eventPhase, ev.AT_TARGET); + assert_equals(sawBubble, true); + assert_equals(sawCapture, false); + sawCapture = true; + } + function handler3(ev) { + assert_equals(ev.eventPhase, ev.AT_TARGET); + assert_equals(sawBubble, true); + assert_equals(sawCapture, true); + sawBubbleTwice = true; + } + + var target = document.getElementById('foo'); + target.addEventListener('foopy', this.step_func(handler), false); + target.addEventListener('foopy', this.step_func(handler2), true); + target.addEventListener('foopy', this.step_func(handler3), false); + var ev = new Event('foopy', {bubbles: true}); + target.dispatchEvent(ev); + assert_equals(sawBubble, true); + assert_equals(sawCapture, true); + assert_equals(sawBubbleTwice, true); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/event_handler_syntax_error.html b/tests/wpt/mozilla/tests/mozilla/event_handler_syntax_error.html new file mode 100644 index 00000000000..78962c67d2c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/event_handler_syntax_error.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<head> + <title></title> + <meta charset="UTF-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <a id="a" onclick="{">link</a> + <script> + test(function() { + var a = document.getElementById("a"); + assert_equals(a.onclick, null, "invalid onclick attribute"); + + document.body.setAttribute("onx", "{"); + document.body.setAttribute("ony", "}"); + + assert_equals(document.body.getAttribute("onx"), "{"); + assert_equals(document.body.getAttribute("ony"), "}"); + }); + </script> +</body> +</html> diff --git a/tests/content/test_event_listener.html b/tests/wpt/mozilla/tests/mozilla/event_listener.html index da040fb2ed6..0ba1ce0d557 100644 --- a/tests/content/test_event_listener.html +++ b/tests/wpt/mozilla/tests/mozilla/event_listener.html @@ -1,13 +1,15 @@ <html> <head> -<script src="harness.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> </head> <body> <script> +test(function() { function onFoopy(ev) { window.removeEventListener('foopy', onFoopy); - is(ev instanceof expected, true); - is(ev.type, 'foopy'); + assert_equals(ev instanceof expected, true); + assert_equals(ev.type, 'foopy'); } var expected; @@ -18,7 +20,7 @@ 0, 0, 0, 0, false, false, false, false, 0, null); }]]; for (var i = 0; i < events.length; i++) { - addEventListener('foopy', onFoopy); + addEventListener('foopy', this.step_func(onFoopy)); expected = events[i][1]; var ev = document.createEvent(events[i][0]); events[i][2](ev); @@ -27,11 +29,12 @@ var constructors = [Event, UIEvent, MouseEvent]; for (var i = 0; i < constructors.length; i++) { - addEventListener('foopy', onFoopy); + addEventListener('foopy', this.step_func(onFoopy)); expected = constructors[i]; var ev = new constructors[i]('foopy', {cancelable: true, bubbles: true}); window.dispatchEvent(ev); } +}); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/focus_blur.html b/tests/wpt/mozilla/tests/mozilla/focus_blur.html new file mode 100644 index 00000000000..83575faf7ad --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/focus_blur.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <input id="a"> + <input id="b"> + <script> + test(function() { + var a = document.getElementById("a"); + var b = document.getElementById("b"); + + assert_equals(document.activeElement, document.body); + a.focus(); + assert_equals(document.activeElement, a); + b.focus(); + assert_equals(document.activeElement, b); + a.blur(); + assert_equals(document.activeElement, b); + b.blur(); + assert_equals(document.activeElement, document.body); + }); + </script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/getBoundingClientRect.html b/tests/wpt/mozilla/tests/mozilla/getBoundingClientRect.html new file mode 100644 index 00000000000..8d65b672072 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/getBoundingClientRect.html @@ -0,0 +1,37 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +div { + position: relative; + top: 100px; + left: 100px; + width: 100px; + height: 100px; +} +</style> +</head> +<body> + <div>my div</div> + <script> + test(function() { + assert_equals(String(DOMRect).indexOf("function DOMRect("), 0); + + var elems = document.getElementsByTagName('div'); + var rect = elems[0].getBoundingClientRect(); + assert_true(rect instanceof DOMRect, "Should be DOMRect"); + + assert_greater_than_equal(rect.top, 100); + assert_greater_than_equal(rect.bottom, 200); + assert_greater_than_equal(rect.left, 100); + assert_greater_than_equal(rect.right, 200); + + assert_equals(rect.width, 100); + assert_equals(rect.height, 100); + assert_equals(rect.width, rect.right - rect.left); + assert_equals(rect.height, rect.bottom - rect.top); + }); + </script> +</body> +</html> diff --git a/tests/content/test_getPropertyPriority.html b/tests/wpt/mozilla/tests/mozilla/getPropertyPriority.html index 85bcde77238..75cd6517ffc 100644 --- a/tests/content/test_getPropertyPriority.html +++ b/tests/wpt/mozilla/tests/mozilla/getPropertyPriority.html @@ -1,10 +1,12 @@ <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <div id="important" style='outline-color: #111 !important; outline-style: solid !important; outline-width: 1px !important; background-color: #222 !important; color: #FFF'></div> <script> + test(function() { var properties = { 'outline-color': 'important', 'outline-style': 'important', @@ -18,8 +20,9 @@ for (var property in Object.keys(properties)) { var name = Object.keys(properties)[property]; var value = properties[name]; - is(elem.style.getPropertyPriority(name), value, name + ' priority'); + assert_equals(elem.style.getPropertyPriority(name), value, name + ' priority'); } + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/global.html b/tests/wpt/mozilla/tests/mozilla/global.html new file mode 100644 index 00000000000..5ce66ed4b40 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/global.html @@ -0,0 +1,16 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +var global = this; +test(function() { + assert_equals(window, window.window); + assert_equals(window, global); + for (var key in global) { + assert_equals(global[key], window[key]); + } +}); +</script> +</head> +</html> diff --git a/tests/content/test_htmlcollection.html b/tests/wpt/mozilla/tests/mozilla/htmlcollection.html index 410c54b2ddf..98098e2e711 100644 --- a/tests/content/test_htmlcollection.html +++ b/tests/wpt/mozilla/tests/mozilla/htmlcollection.html @@ -1,7 +1,8 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <div id="foo-1" class="foo"></div> @@ -25,93 +26,88 @@ let htmlcollection = null; - // test1: HTMLCollection interface - { + test(function() { htmlcollection = document.getElementsByClassName("foo"); - is(htmlcollection.length, 2); - is(htmlcollection.item(0), foo1); - is(htmlcollection.item(1), foo2); - is(htmlcollection.item(2), null); - is(htmlcollection.namedItem("foo-1"), foo1); - is(htmlcollection.namedItem("bar"), null); + assert_equals(htmlcollection.length, 2); + assert_equals(htmlcollection.item(0), foo1); + assert_equals(htmlcollection.item(1), foo2); + assert_equals(htmlcollection.item(2), null); + assert_equals(htmlcollection.namedItem("foo-1"), foo1); + assert_equals(htmlcollection.namedItem("bar"), null); htmlcollection = document.getElementsByClassName("FOO"); - is(htmlcollection.length, 0); + assert_equals(htmlcollection.length, 0); htmlcollection = document.getElementsByClassName("bar"); - is(htmlcollection.length, 1); - is(htmlcollection.item(0), bar); - is(htmlcollection.item(1), null); - is(htmlcollection.namedItem("bar"), bar); - } - - // test2: live HTMLCollection - { + assert_equals(htmlcollection.length, 1); + assert_equals(htmlcollection.item(0), bar); + assert_equals(htmlcollection.item(1), null); + assert_equals(htmlcollection.namedItem("bar"), bar); + }, "HTMLCollection interface"); + + test(function() { htmlcollection = document.getElementsByClassName("live"); - is(htmlcollection.length, 1); - is(htmlcollection.item(0), live); + assert_equals(htmlcollection.length, 1); + assert_equals(htmlcollection.item(0), live); let new_live = document.createElement("div"); new_live.className = "live"; document.body.appendChild(new_live); - is(htmlcollection.length, 2); - is(htmlcollection.item(1), new_live); + assert_equals(htmlcollection.length, 2); + assert_equals(htmlcollection.item(1), new_live); document.body.removeChild(new_live); - is(htmlcollection.length, 1); - } + assert_equals(htmlcollection.length, 1); + }, "live HTMLCollection"); - // test3: getElementsByTagName - { - is(document.getElementsByTagName("DIV").length, 5); + test(function() { + assert_equals(document.getElementsByTagName("DIV").length, 5); - is(document.getElementsByTagName("div").length, + assert_equals(document.getElementsByTagName("div").length, document.documentElement.getElementsByTagName("div").length); - is(document.getElementsByTagName("p").length, + assert_equals(document.getElementsByTagName("p").length, document.getElementById("class-example").getElementsByTagName("p").length); - } + }, "getElementsByTagName"); - // test4: getElementsByTagNameNS - { + test(function() { htmlcollection = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "div"); - is(htmlcollection.length, 5); + assert_equals(htmlcollection.length, 5); let from_element = document.documentElement.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "div"); - is(htmlcollection.length, from_element.length); + assert_equals(htmlcollection.length, from_element.length); htmlcollection = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "DIV"); - is(htmlcollection.length, 0); + assert_equals(htmlcollection.length, 0); htmlcollection = document.getElementsByTagNameNS("", "div"); - is(htmlcollection.length, 0); + assert_equals(htmlcollection.length, 0); htmlcollection = document.getElementsByTagNameNS("invalid", "div"); - is(htmlcollection.length, 0); + assert_equals(htmlcollection.length, 0); from_element = document.getElementById("class-example").getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "p"); - is(from_element.length, 3); - } + assert_equals(from_element.length, 3); + }, "getElementsByTagNameNS"); - // test5: document.getElementsByClassName - { + test(function() { htmlcollection = document.getElementsByClassName("aaa"); - is(htmlcollection.length, 2); - is(htmlcollection.item(0), p1); - is(htmlcollection.item(1), p2); + assert_equals(htmlcollection.length, 2); + assert_equals(htmlcollection.item(0), p1); + assert_equals(htmlcollection.item(1), p2); htmlcollection = document.getElementsByClassName("ccc bbb"); - is(htmlcollection.length, 1); - is(htmlcollection.item(0), p3); + assert_equals(htmlcollection.length, 1); + assert_equals(htmlcollection.item(0), p3); htmlcollection = document.getElementsByClassName("aaa,bbb"); - is(htmlcollection.length, 0); + assert_equals(htmlcollection.length, 0); let from_element = document.getElementById("class-example").getElementsByClassName("bbb"); - is(from_element.length, 2); - is(from_element.item(0), p1); - is(from_element.item(1), p3); - } + assert_equals(from_element.length, 2); + assert_equals(from_element.item(0), p1); + assert_equals(from_element.item(1), p3); + }, "document.getElementsByClassName"); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/htmlfieldsetelement_elements.html b/tests/wpt/mozilla/tests/mozilla/htmlfieldsetelement_elements.html new file mode 100644 index 00000000000..ee0ea4ae15f --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/htmlfieldsetelement_elements.html @@ -0,0 +1,47 @@ +<html> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <fieldset id="fs"> + <legend>Display</legend> + <input type=radio name=a> + <fieldset> + <button>Click!</button> + </fieldset> + <keygen name="key"> + <textarea> + A + </textarea> + <select> + <option value="1"> A </option> + <option value="2" selected> B </option> + </select> + <form onsubmit="return false" oninput="o.value = a.valueAsNumber + b.valueAsNumber"> + <input name=a type=number step=any> + + <input name=b type=number step=any> = + <output name=c for="a b"></output> + </form> + <figure> + <object type="application/x-java-applet"> + <param name="code" value="MyJavaClass"> + <p>You do not have Java available, or it is disabled.</p> + </object> + <figcaption>My Java Clock</figcaption> + </figure> + </fieldset> + <script> + test(function() { + var fs = document.getElementById("fs"); + assert_equals(fs.elements.length, 10); + assert_true(fs.elements[0] instanceof HTMLInputElement, "Should be HTMLInputElement"); + assert_true(fs.elements[1] instanceof HTMLFieldSetElement, "Should be HTMLFieldSetElement"); + assert_true(fs.elements[2] instanceof HTMLButtonElement, "Should be HTMLButtonElement"); + assert_true(fs.elements[3] instanceof HTMLUnknownElement, "Should be HTMLUnknownElement"); + assert_true(fs.elements[4] instanceof HTMLTextAreaElement, "Should be HTMLTextAreaElement"); + assert_true(fs.elements[5] instanceof HTMLSelectElement, "Should be HTMLSelectElement"); + assert_true(fs.elements[6] instanceof HTMLInputElement, "Should be HTMLInputElement"); + assert_true(fs.elements[7] instanceof HTMLInputElement, "Should be HTMLInputElement"); + assert_true(fs.elements[8] instanceof HTMLOutputElement, "Should be HTMLOutputElement"); + assert_true(fs.elements[9] instanceof HTMLObjectElement, "Should be HTMLObjectElement"); + }); + </script> +</html> diff --git a/tests/content/test_htmlspacechars.html b/tests/wpt/mozilla/tests/mozilla/htmlspacechars.html index fbb6046d8c3..31cb0c0be6c 100644 --- a/tests/content/test_htmlspacechars.html +++ b/tests/wpt/mozilla/tests/mozilla/htmlspacechars.html @@ -1,7 +1,8 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <!-- \u0020 Space --> @@ -19,8 +20,10 @@ <!-- Non-HTML space character --> <div id="bar" class="gggfoo"></div> <script> - is(document.getElementsByClassName("foo").length, 6); - is_not(document.getElementById("bar").className, "ggg foo"); + test(function() { + assert_equals(document.getElementsByClassName("foo").length, 6); + assert_not_equals(document.getElementById("bar").className, "ggg foo"); + }); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/iframe_contentDocument.html b/tests/wpt/mozilla/tests/mozilla/iframe_contentDocument.html new file mode 100644 index 00000000000..28dd011d2cf --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/iframe_contentDocument.html @@ -0,0 +1,28 @@ +<html> +<head> +<meta charset="utf8" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<title>Iframe contentDocument test.</title> +</head> +<body> +<iframe src="resources/iframe_contentDocument_inner.html" id="iframe"></iframe> +<script> +async_test(function() { + var timeout = 100; + var iframe = document.getElementById('iframe'); + function test_contentWindow() { + if (!iframe.contentWindow) { + // Iframe not loaded yet, try again. + // No load event for iframe, insert bug number here. + setTimeout(this.step_func(test_contentWindow), timeout); + return; + } + assert_equals(iframe.contentDocument.getElementById('test').textContent, 'value'); + this.done(); + } + this.step(test_contentWindow); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/img_width_height.html b/tests/wpt/mozilla/tests/mozilla/img_width_height.html new file mode 100644 index 00000000000..c792668083c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/img_width_height.html @@ -0,0 +1,33 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <img src="test.png"/> +<script> +// Testing get/set of image width/height properties +async_test(function() { + var img = window.document.getElementsByTagName("img")[0]; + + var wait_for_img_load = this.step_func(function (f) { + if (img.width != 0) { + f(); + } else { + window.setTimeout(function() { wait_for_img_load(f) }, 1); + } + }); + + wait_for_img_load(this.step_func_done(function() { + assert_equals(img.width, 500); + assert_equals(img.height, 378); + img.width = 200; + img.height = 100; + assert_equals(img.width, 200); + assert_equals(img.height, 100); + })); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/inline_event_handler.html b/tests/wpt/mozilla/tests/mozilla/inline_event_handler.html new file mode 100644 index 00000000000..4f86be5b9cb --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/inline_event_handler.html @@ -0,0 +1,11 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body onload="t.step(function() { assert_true(event instanceof Event, 'Should be Event'); this.done(); })"> +<script> +var t = async_test(); +</script> +</body> +</html> diff --git a/tests/content/test_innerHTML.html b/tests/wpt/mozilla/tests/mozilla/innerHTML.html index b140cfbe894..031e67e0c3b 100644 --- a/tests/content/test_innerHTML.html +++ b/tests/wpt/mozilla/tests/mozilla/innerHTML.html @@ -1,12 +1,15 @@ <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> <script> + test(function() { var a = document.createElement("div"); a.appendChild(document.createElement("pre")).appendChild(new Text("")); var b = document.createElement("div"); b.appendChild(a); - is(b.innerHTML, "<div><pre></pre></div>"); + assert_equals(b.innerHTML, "<div><pre></pre></div>"); + }); </script> </head> </html> diff --git a/tests/content/test_interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.html index cb566e4ce1a..9649a9f3e15 100644 --- a/tests/content/test_interfaces.html +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.html @@ -1,7 +1,8 @@ <!DOCTYPE HTML> <meta charset=utf-8> <title>Interfaces exposed on the window</title> -<script src="harness.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> <script> // This is a list of all interfaces that are exposed to every webpage. // Please only add things to this list with great care and proper review @@ -89,6 +90,7 @@ var interfaceNamesInGlobalScope = [ "HTMLCollection", "HTMLDataElement", "HTMLDataListElement", + "HTMLDialogElement", "HTMLDirectoryElement", "HTMLDivElement", "HTMLDListElement", @@ -154,6 +156,7 @@ var interfaceNamesInGlobalScope = [ "NamedNodeMap", "Navigator", "Node", + "NodeFilter", "NodeIterator", "NodeList", "Performance", @@ -166,11 +169,13 @@ var interfaceNamesInGlobalScope = [ "StorageEvent", "TestBinding", // XXX "Text", + "TextDecoder", "TextEncoder", "TreeWalker", "UIEvent", "URLSearchParams", "ValidityState", + "WebGLRenderingContext", "WebSocket", "Window", "Worker", @@ -194,26 +199,30 @@ function createInterfaceMap() { addInterfaces(ecmaGlobals); addInterfaces(interfaceNamesInGlobalScope); + addInterfaces(["EventWatcher"]); return interfaceMap; } -var interfaceMap = createInterfaceMap(); -for (var name of Object.getOwnPropertyNames(window)) { - if (!/^[A-Z]/.test(name)) { - continue; +test(function() { + var interfaceMap = createInterfaceMap(); + for (var name of Object.getOwnPropertyNames(window)) { + if (!/^[A-Z]/.test(name)) { + continue; + } + assert_true(name in interfaceMap, + "If this is failing: DANGER, are you sure you want to expose the new " + + "interface " + name + " to all webpages as a property on the window? " + + "Do not make a change to this file without review from jdm or Ms2ger " + + "for that specific change!"); + if (name in interfaceMap) { + delete interfaceMap[name]; + } } - is_in(name, interfaceMap, - "If this is failing: DANGER, are you sure you want to expose the new " + - "interface " + name + " to all webpages as a property on the window? " + - "Do not make a change to this file without review from jdm or Ms2ger " + - "for that specific change!"); - if (name in interfaceMap) { - delete interfaceMap[name]; + for (var name of Object.keys(interfaceMap)) { + assert_true(name in window, name + " should be defined on the global scope"); } -} -for (var name of Object.keys(interfaceMap)) { - is_in(name, window, name + " should be defined on the global scope"); -} -is(Object.keys(interfaceMap).length, 0, - "The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", ")); + assert_equals(Object.keys(interfaceMap).length, 0, + "The following interface(s) are not enumerated: " + + Object.keys(interfaceMap).join(", ")); +}); </script> diff --git a/tests/wpt/mozilla/tests/mozilla/lenient_this.html b/tests/wpt/mozilla/tests/mozilla/lenient_this.html new file mode 100644 index 00000000000..960c74613f3 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/lenient_this.html @@ -0,0 +1,22 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + var handler = function () { }; + document.onreadystatechange = handler; + var obj = {}; + + test(function() { + var val = Object.getOwnPropertyDescriptor(Document.prototype, "onreadystatechange").get.call(document); + assert_equals(val, handler, "test1-0, basic test"); + }, "basic test"); + + test(function() { + var val = Object.getOwnPropertyDescriptor(Document.prototype, "onreadystatechange").get.call(obj); + assert_equals(val, undefined, "test2-0, calling getter returns undefined"); + assert_equals(Document.prototype.onreadystatechange, undefined, "test2-1, property access returns undefined"); + }, 'Should not throw for attribute marked "[LenientThis]"'); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/load_event.html b/tests/wpt/mozilla/tests/mozilla/load_event.html new file mode 100644 index 00000000000..091909ee81c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/load_event.html @@ -0,0 +1,32 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +async_test(function() { + var onloads = 0; + function check(ev) { + assert_true(ev instanceof Event, "Should be Event"); + ev.preventDefault(); + assert_equals(ev.defaultPrevented, false); + assert_equals(ev.target, document); + assert_equals(ev.currentTarget, window); + } + + window.onload = this.unreached_func("this inline handler should be overwritten"); + window.onload = this.step_func(function(ev) { + onloads++; + assert_equals(onloads, 1); + check(ev); + }); + addEventListener("load", this.step_func_done(function(ev) { + onloads++; + assert_equals(onloads, 2); + check(ev); + })); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/navigator.html b/tests/wpt/mozilla/tests/mozilla/navigator.html new file mode 100644 index 00000000000..83f74b6e6cf --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/navigator.html @@ -0,0 +1,23 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + assert_equals(window.navigator, window.navigator); + assert_true(window.navigator instanceof Navigator, "Should be Navigator"); + + var nav = window.navigator; + assert_equals(nav.product, "Gecko"); + assert_equals(nav.taintEnabled(), false); + assert_equals(nav.appName, "Netscape"); + assert_equals(nav.appCodeName, "Mozilla"); + assert_equals(nav.platform, ""); + assert_equals(nav.appVersion, "4.0"); +}); +</script> +</body> +</html> diff --git a/tests/content/test_node_cloneNode.html b/tests/wpt/mozilla/tests/mozilla/node_cloneNode.html index 7342ba9eb8c..b2ab789af00 100644 --- a/tests/content/test_node_cloneNode.html +++ b/tests/wpt/mozilla/tests/mozilla/node_cloneNode.html @@ -1,22 +1,25 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> <script> function check_copy(orig, copy, type) { - is_not(orig, copy); - is_a(orig, type); - is_a(copy, type); + assert_not_equals(orig, copy); + assert_true(orig instanceof type, "Should be type"); + assert_true(copy instanceof type, "Should be type"); } function create_element_and_check(localName, type) { + test(function() { var element = document.createElement(localName); var copy = element.cloneNode(); check_copy(element, copy, type); + }, "createElement(" + localName + ")"); } // test1: createElement - { + test(function() { create_element_and_check("a", HTMLAnchorElement); create_element_and_check("abbr", HTMLElement); create_element_and_check("acronym", HTMLElement); @@ -139,66 +142,58 @@ create_element_and_check("video", HTMLVideoElement); create_element_and_check("unknown", HTMLUnknownElement); create_element_and_check("wbr", HTMLElement); - } + }, ""); - // test2: createDocumentFragment - { + test(function() { var fragment = document.createDocumentFragment(); var copy = fragment.cloneNode(); check_copy(fragment, copy, DocumentFragment); - } + }, "createDocumentFragment"); - // test3: createTextNode - { + test(function() { var text = document.createTextNode("hello world"); var copy = text.cloneNode(); check_copy(text, copy, Text); - is(text.data, copy.data); - is(text.wholeText, copy.wholeText); - } + assert_equals(text.data, copy.data); + assert_equals(text.wholeText, copy.wholeText); + }, "createTextNode"); - // test4: createComment - { + test(function() { var comment = document.createComment("a comment"); var copy = comment.cloneNode(); check_copy(comment, copy, Comment); - is(comment.data, copy.data); - } + assert_equals(comment.data, copy.data); + }, "createComment"); - // test5: createProcessingInstruction - { + test(function() { var pi = document.createProcessingInstruction("target", "data"); var copy = pi.cloneNode(); check_copy(pi, copy, ProcessingInstruction); - is(pi.data, copy.data); - is(pi.target, pi.target); - } + assert_equals(pi.data, copy.data); + assert_equals(pi.target, pi.target); + }, "createProcessingInstruction"); - // test6: implementation.createDocumentType - { + test(function() { var doctype = document.implementation.createDocumentType("html", "public", "system"); var copy = doctype.cloneNode(); check_copy(doctype, copy, DocumentType); - is(doctype.name, copy.name); - is(doctype.publicId, copy.publicId); - is(doctype.systemId, copy.systemId); - } + assert_equals(doctype.name, copy.name); + assert_equals(doctype.publicId, copy.publicId); + assert_equals(doctype.systemId, copy.systemId); + }, "implementation.createDocumentType"); - // test7: implementation.createDocument - { + test(function() { // FIXME: https://github.com/mozilla/servo/issues/1509 - } + }, "implementation.createDocument"); - // test8: implementation.createHTMLDocument - { + test(function() { var html = document.implementation.createHTMLDocument("title"); var copy = html.cloneNode(); check_copy(html, copy, Document); - is(html.title, copy.title); - } + assert_equals(html.title, copy.title); + }, "implementation.createHTMLDocument"); - // test9: node with children - { + test(function() { var parent = document.createElement("div"); var child1 = document.createElement("div"); var child2 = document.createElement("div"); @@ -212,21 +207,21 @@ var copy = parent.cloneNode(deep); check_copy(parent, copy, HTMLDivElement); - is(copy.childNodes.length, 2); + assert_equals(copy.childNodes.length, 2); check_copy(child1, copy.childNodes[0], HTMLDivElement); - is(copy.childNodes[0].childNodes.length, 0); + assert_equals(copy.childNodes[0].childNodes.length, 0); check_copy(child2, copy.childNodes[1], HTMLDivElement); - is(copy.childNodes[1].childNodes.length, 1); + assert_equals(copy.childNodes[1].childNodes.length, 1); check_copy(grandChild, copy.childNodes[1].childNodes[0], HTMLDivElement); deep = false; copy = parent.cloneNode(deep); check_copy(parent, copy, HTMLDivElement); - is(copy.childNodes.length, 0); - } + assert_equals(copy.childNodes.length, 0); + }, "node with children"); </script> </head> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_compareDocumentPosition.html b/tests/wpt/mozilla/tests/mozilla/node_compareDocumentPosition.html new file mode 100644 index 00000000000..67a73b7f06f --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_compareDocumentPosition.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + var elem = document.createElement("div"); + var other = document.createElement("div"); + assert_equals(elem.compareDocumentPosition(elem),0); + + var nonTree = elem.compareDocumentPosition(other); + var prefix = Node.DOCUMENT_POSITION_DISCONNECTED + Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + assert_equals(nonTree == prefix + Node.DOCUMENT_POSITION_FOLLOWING || nonTree == prefix + Node.DOCUMENT_POSITION_PRECEDING, + true); + + elem.appendChild(other); + assert_equals(elem.compareDocumentPosition(other), Node.DOCUMENT_POSITION_CONTAINED_BY + Node.DOCUMENT_POSITION_FOLLOWING); + assert_equals(other.compareDocumentPosition(elem), Node.DOCUMENT_POSITION_CONTAINS + Node.DOCUMENT_POSITION_PRECEDING); + + var another = document.createElement("div"); + other.appendChild(another); + assert_equals(elem.compareDocumentPosition(another), Node.DOCUMENT_POSITION_CONTAINED_BY + Node.DOCUMENT_POSITION_FOLLOWING); + assert_equals(another.compareDocumentPosition(elem), Node.DOCUMENT_POSITION_CONTAINS + Node.DOCUMENT_POSITION_PRECEDING); + + var follower = document.createElement("div"); + elem.appendChild(follower); + var preceder = document.createElement("div"); + another.appendChild(preceder); + assert_equals(another.compareDocumentPosition(follower), Node.DOCUMENT_POSITION_FOLLOWING); + assert_equals(follower.compareDocumentPosition(another), Node.DOCUMENT_POSITION_PRECEDING); + assert_equals(follower.compareDocumentPosition(preceder), Node.DOCUMENT_POSITION_PRECEDING); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_contains.html b/tests/wpt/mozilla/tests/mozilla/node_contains.html new file mode 100644 index 00000000000..d76471fec9d --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_contains.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + var parent = document.createElement("div"); + var child = document.createElement("div"); + var child_of_child = document.createElement("div"); + var other = document.createElement("div"); + + child.appendChild(child_of_child); + parent.appendChild(child); + + assert_equals(parent.contains(parent), true, "test1-0, Node.contains"); + assert_equals(parent.contains(child), true, "test1-1, Node.contains"); + assert_equals(parent.contains(child_of_child), true, "test1-2, Node.contains"); + assert_equals(parent.contains(other), false, "test1-3, Node.contains"); + }); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_insertBefore.html b/tests/wpt/mozilla/tests/mozilla/node_insertBefore.html new file mode 100644 index 00000000000..27f4e9182e2 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_insertBefore.html @@ -0,0 +1,23 @@ +<!doctype html> +<html> + <head> + <title>Node.insertBefore</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script type="text/javascript"> + test(function() { + var root = document.createElement("div"); + var after = document.createElement("div"); + var before = document.createElement("div"); + + root.appendChild(after); + + assert_equals(root.insertBefore(before, after), before, "test1-0, insertBefore"); + assert_equals(root.childNodes[0], before, "test1-1, insertBefore"); + assert_equals(root.childNodes[1], after, "test1-2, insertBefore"); + }); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_isEqualNode.html b/tests/wpt/mozilla/tests/mozilla/node_isEqualNode.html new file mode 100644 index 00000000000..ab8e54bb1aa --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_isEqualNode.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + test(function() { + var elem = document.createElement("div"); + var other = document.createElement("div"); + assert_equals(elem.isEqualNode(elem), true); + assert_equals(elem.isEqualNode(other), true); + assert_equals(other.isEqualNode(elem), true); + assert_equals(elem.isEqualNode(document), false); + }, "simple checks"); + + test(function() { + var parent_elem = document.createElement("div"); + var child_elem = document.createElement("div"); + parent_elem.appendChild(child_elem); + + var other_parent = document.createElement("div"); + var other_child = document.createElement("div"); + other_parent.appendChild(other_child); + + assert_equals(parent_elem.isEqualNode(other_parent), true); + assert_equals(child_elem.isEqualNode(other_child), true); + + var child_text = document.createTextNode("lorem ipsum"); + child_elem.appendChild(child_text); + + assert_equals(parent_elem.isEqualNode(other_parent), false); + assert_equals(child_elem.isEqualNode(other_child), false); + }, "non-element children"); + </script> + </head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_lookupPrefix.html b/tests/wpt/mozilla/tests/mozilla/node_lookupPrefix.html new file mode 100644 index 00000000000..dfd898dc85f --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_lookupPrefix.html @@ -0,0 +1,51 @@ +<!doctype html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <x xarg="xval"> + <!--comment--> + <?test test?> + TEST + <x/> + </x> + <script> + test(function() { + document.documentElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:x", "test"); + document.body.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:s", "test"); + var x = document.getElementsByTagName("x")[0]; + x.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:t", "test"); + var yprefix = document.createElementNS("ynamespace", "yprefix:ylocalname"); + var ynoprefix = document.createElementNS("ynamespace", "ylocalname"); + ynoprefix.setAttribute("ynoprefixattr", "yval"); + ynoprefix.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:yattr", "yval"); + + // Step 1 + assert_equals(document.lookupPrefix(""), null); + assert_equals(document.lookupPrefix(null), null); + + // Element step 1 + assert_equals(yprefix.lookupPrefix("ynamespace"), "yprefix"); + assert_equals(ynoprefix.lookupPrefix("ynamespace"), null); + + // Element step 2 + assert_equals(x.lookupPrefix("test"), "t"); + assert_equals(ynoprefix.lookupPrefix("yval"), "yattr"); + + // analogous to wpt - https://github.com/w3c/web-platform-tests/blob/master/dom/nodes/Node-lookupPrefix.xhtml + assert_equals(document.lookupPrefix("test"), "x"); + assert_equals(x.lookupPrefix("test"), "t"); + assert_equals(x.lookupPrefix("http://www.w3.org/1999/xhtml"), null); + assert_equals(x.lookupPrefix("something"), null); + assert_equals(x.lookupPrefix(null), null); + assert_equals(x.parentNode.lookupPrefix("test"), "s"); + assert_equals(x.firstChild.lookupPrefix("test"), "t"); + assert_equals(x.childNodes[1].lookupPrefix("test"), "t"); + assert_equals(x.childNodes[2].lookupPrefix("test"), "t"); + assert_equals(x.lastChild.lookupPrefix("test"), "t"); + }); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_normalize.html b/tests/wpt/mozilla/tests/mozilla/node_normalize.html new file mode 100644 index 00000000000..4b333150332 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_normalize.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + test(function() { + var parent1 = document.createElement("div"); + var child1 = document.createTextNode("aaa"); + var child2 = document.createTextNode(""); + var child3 = document.createTextNode("bb"); + + var parent2 = document.createElement("div"); + + parent1.appendChild(child1); + parent1.appendChild(child2); + parent1.appendChild(child3); + + parent2.appendChild(document.createTextNode("")); + + parent1.normalize(); + parent2.normalize(); + + assert_equals(Array.prototype.map.call(parent1.childNodes, function(el) {return el.length}).indexOf(0), -1, "Node.normalize removes empty text nodes"); + assert_equals(parent1.childNodes.length, 1, "Node.normalize merges text nodes in one"); + assert_equals(parent1.childNodes[0].length, 5, "test 1-2, Node.normalize merges text nodes values"); + assert_equals(parent2.childNodes.length, 0, "Node.normalize removes empty text nodes even if there is only one text node"); + assert_equals(child2.textContent, "", "Node.normalize doesn't change removed children original content") + assert_equals(child3.textContent, "bb", "Node.normalize doesn't change removed children original content") + }); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/node_replaceChild.html b/tests/wpt/mozilla/tests/mozilla/node_replaceChild.html new file mode 100644 index 00000000000..a0ea4ffc179 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/node_replaceChild.html @@ -0,0 +1,48 @@ +<!doctype html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + test(function() { + var root = document.createElement("div"); + var elem = document.createElement("div"); + var foo = document.createTextNode("foo"); + var bar = document.createTextNode("bar"); + + elem.appendChild(bar); + assert_equals(elem.replaceChild(bar, bar), bar, "test1-0, 1-to-1"); + assert_equals(elem.childNodes[0], bar, "test1-1, 1-to-1"); + + root.appendChild(foo); + assert_equals(root.replaceChild(bar, foo), foo, "test1-2, 1-to-1"); + assert_equals(elem.childNodes.length, 0, "test1-3, 1-to-1"); + assert_equals(root.childNodes[0], bar, "test1-4, 1-to-1"); + + elem.appendChild(foo); + assert_equals(root.replaceChild(elem, bar), bar, "test1-5, 1-to-1"); + assert_equals(root.childNodes[0].childNodes[0], foo, "test1-6, 1-to-1"); + }, "1-to-1"); + + test(function() { + var doc_doctype = document.doctype; + var new_doctype = document.implementation.createDocumentType("html", null, null); + + assert_not_equals(doc_doctype, new_doctype, "test2-0, doctype"); + assert_equals(document.replaceChild(new_doctype, doc_doctype), doc_doctype, "test2-1, doctype"); + assert_equals(document.doctype, new_doctype, "test2-2, doctype"); + }, "doctype"); + + test(function() { + var doc_elem = document.documentElement; + var new_elem = document.createElement("html"); + + assert_not_equals(doc_elem, new_elem, "test3-0, documentElement"); + assert_equals(document.replaceChild(new_elem, doc_elem), doc_elem, "test3-1, documentElement"); + assert_equals(document.documentElement, new_elem, "test3-2, documentElement"); + }, "documentElement"); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/parentNode_querySelector.html b/tests/wpt/mozilla/tests/mozilla/parentNode_querySelector.html new file mode 100644 index 00000000000..3239f15ab00 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/parentNode_querySelector.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id="foo"></div> + <div id="foo\bar"></div> + <div id="foo:bar"></div> + <div id="bar" class="myClass"></p> + <script> + test(function() { + let div = document.getElementById("foo"); + assert_equals(document.querySelector("#foo"), div); + + div = document.getElementById("foo\\bar"); + assert_equals(document.querySelector("#foo\\\\bar"), div); + + div = document.getElementById("foo:bar"); + assert_equals(document.querySelector("#foo\\:bar"), div); + + div = document.getElementById("bar"); + assert_equals(document.querySelector("div.myClass"), div); + assert_equals(document.querySelector("div:nth-of-type(4)"), div); + }, "Document"); + + test(function() { + let body = document.body; + let div = document.getElementById("foo"); + assert_equals(body.querySelector("#foo"), div); + + div = document.getElementById("foo\\bar"); + assert_equals(body.querySelector("#foo\\\\bar"), div); + + div = document.getElementById("foo:bar"); + assert_equals(body.querySelector("#foo\\:bar"), div); + + div = document.getElementById("bar"); + assert_equals(body.querySelector("div.myClass"), div); + assert_equals(body.querySelector("div:nth-of-type(4)"), div); + }, "Element"); + + test(function() { + let docfrag = document.createDocumentFragment(); + + let div = document.createElement("div"); + div.id = "foo"; + div.className = "myClass"; + + let child = document.createElement("div"); + div.appendChild(child); + docfrag.appendChild(div); + + let p = document.createElement("p"); + p.id = "bar"; + p.className = "myClass"; + docfrag.appendChild(p); + + assert_equals(docfrag.querySelector("#foo"), div); + assert_equals(docfrag.querySelector("div.myClass"), div); + + assert_equals(docfrag.querySelector("#bar"), p); + assert_equals(docfrag.querySelector("p.myClass"), p); + + assert_equals(docfrag.querySelector(".myClass"), div); + assert_equals(docfrag.querySelector("div > div"), child); + }, "DocumentFragment"); + </script> + </body> +</html> diff --git a/tests/content/test_parentNode_querySelectorAll.html b/tests/wpt/mozilla/tests/mozilla/parentNode_querySelectorAll.html index bc99a8251a6..f52ccee7541 100644 --- a/tests/content/test_parentNode_querySelectorAll.html +++ b/tests/wpt/mozilla/tests/mozilla/parentNode_querySelectorAll.html @@ -1,7 +1,8 @@ <!DOCTYPE html> <html> <head> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <div id="parent"> @@ -14,28 +15,28 @@ let bar = document.getElementById("bar"); let baz = document.getElementById("baz"); - { // document.querySelector + test(function() { let nodelist = document.querySelectorAll(".test"); - is_a(nodelist, NodeList); - is(nodelist.length, 3); - is(nodelist.item(0), foo); - is(nodelist.item(1), bar); - is(nodelist.item(2), baz); + assert_true(nodelist instanceof NodeList, "Should be NodeList"); + assert_equals(nodelist.length, 3); + assert_equals(nodelist.item(0), foo); + assert_equals(nodelist.item(1), bar); + assert_equals(nodelist.item(2), baz); nodelist = document.querySelectorAll("div > .test"); - is(nodelist.length, 3); - } + assert_equals(nodelist.length, 3); + }, "Document"); - { // element.querySelector + test(function() { let div = document.getElementById("parent"); let nodelist = div.querySelectorAll(".test"); - is(nodelist.length, 3); + assert_equals(nodelist.length, 3); nodelist = div.querySelectorAll("div:nth-of-type(1)"); - is(nodelist.item(0), div); - } + assert_equals(nodelist.item(0), div); + }, "Element"); - { // docfrag.querySelector + test(function() { let docfrag = document.createDocumentFragment(); let div = document.createElement("div"); @@ -47,11 +48,11 @@ docfrag.appendChild(div); let nodelist = docfrag.querySelectorAll("#foo"); - is(nodelist.item(0), div); + assert_equals(nodelist.item(0), div); nodelist = docfrag.querySelectorAll("#foo:nth-child(1)"); - is(nodelist.item(0), div); - } + assert_equals(nodelist.item(0), div); + }, "DocumentFragment"); </script> </body> </html> diff --git a/tests/wpt/mozilla/tests/mozilla/parentnodes.html b/tests/wpt/mozilla/tests/mozilla/parentnodes.html new file mode 100644 index 00000000000..5effbcdfdab --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/parentnodes.html @@ -0,0 +1,26 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="div1"></div> + <script> + test(function() { + assert_true(document.documentElement.parentNode instanceof Document, "Should be Document"); + assert_equals(document.documentElement.parentElement, null); + + var elem = document.createElement("p"); + assert_equals(elem.parentNode, null); + assert_equals(elem.parentElement, null); + + var child = document.createElement("p"); + elem.appendChild(child); + + assert_equals(child.parentNode, elem); + assert_equals(child.parentElement, elem); + }); + </script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/proxy_setter.html b/tests/wpt/mozilla/tests/mozilla/proxy_setter.html new file mode 100644 index 00000000000..b8d3d8e9cfb --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/proxy_setter.html @@ -0,0 +1,16 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + assert_equals(window.document.title, ''); + window.document.title = 'foo'; + assert_equals(window.document.title, 'foo'); +}); +</script> +</body> +</html> diff --git a/tests/content/resources/iframe_contentDocument_inner.html b/tests/wpt/mozilla/tests/mozilla/resources/iframe_contentDocument_inner.html index 2fb85a9b2c2..2fb85a9b2c2 100644 --- a/tests/content/resources/iframe_contentDocument_inner.html +++ b/tests/wpt/mozilla/tests/mozilla/resources/iframe_contentDocument_inner.html diff --git a/tests/content/test_script_type.html b/tests/wpt/mozilla/tests/mozilla/script_type.html index 2a67db887cf..e05202e7371 100644 --- a/tests/content/test_script_type.html +++ b/tests/wpt/mozilla/tests/mozilla/script_type.html @@ -1,13 +1,21 @@ <html> <head> <title></title> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <script> - expect(22); - function ok(msg) { _pass(msg, ""); } - function fail(msg) { _fail(msg, ""); } + async_test(function() { + var executed = 0; + window.ok = this.step_func(function() { + ++executed; + }) + window.fail = this.unreached_func() + window.onload = this.step_func_done(function() { + assert_equals(executed, 22); + }); + }); </script> <script type=""> ok('type is empty string'); diff --git a/tests/content/test_storage.html b/tests/wpt/mozilla/tests/mozilla/storage.html index e8322d29496..375c537a1b3 100644 --- a/tests/content/test_storage.html +++ b/tests/wpt/mozilla/tests/mozilla/storage.html @@ -1,14 +1,17 @@ <html> <head> <title></title> - <script src="harness.js"></script> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> </head> <body> <script> + test(function() { // Delete keys that don't exist in either localStorage // or sessionStorage. delete localStorage.a; delete sessionStorage.a; + }); </script> </body> </html> diff --git a/tests/content/test.jpg b/tests/wpt/mozilla/tests/mozilla/test.jpg Binary files differindex 110b3d6b666..110b3d6b666 100644 --- a/tests/content/test.jpg +++ b/tests/wpt/mozilla/tests/mozilla/test.jpg diff --git a/tests/content/test.png b/tests/wpt/mozilla/tests/mozilla/test.png Binary files differindex 353869b3c49..353869b3c49 100644 --- a/tests/content/test.png +++ b/tests/wpt/mozilla/tests/mozilla/test.png diff --git a/tests/wpt/mozilla/tests/mozilla/textcontent.html b/tests/wpt/mozilla/tests/mozilla/textcontent.html new file mode 100644 index 00000000000..c89bb1b640f --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/textcontent.html @@ -0,0 +1,19 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div>this is + text content</div> +<script> +test(function() { + var div = document.getElementsByTagName('div')[0]; + assert_equals(div.textContent, "this is\n text content"); + var newContent = "new text con\ntent"; + div.textContent = newContent; + assert_equals(div.textContent, newContent); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/title.html b/tests/wpt/mozilla/tests/mozilla/title.html new file mode 100644 index 00000000000..d4e55bc43f7 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/title.html @@ -0,0 +1,14 @@ +<html> +<head> +<title>starting title</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(document.title, "starting title"); + document.title = "new title"; + assert_equals(document.title, "new title"); +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/trace_null.html b/tests/wpt/mozilla/tests/mozilla/trace_null.html new file mode 100644 index 00000000000..bb4f8c1fc52 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/trace_null.html @@ -0,0 +1,9 @@ +<!-- crashtest --> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + new CustomEvent("foo", { detail: null }); + gc(); +}); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/union.html b/tests/wpt/mozilla/tests/mozilla/union.html new file mode 100644 index 00000000000..d9116cd7bde --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/union.html @@ -0,0 +1,24 @@ +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<select id="sel"></select> +<script> +test(function() { + var div = document.createElement('div'); + var optgroup = document.createElement('optgroup'); + var sel = document.getElementById('sel'); + + var opt = document.createElement('option'); + sel.add(opt); + sel.add(optgroup); + sel.add(opt, div); + sel.add(optgroup, div); + sel.add(opt, 5); + sel.add(optgroup, 5); + assert_throws(null, function() { sel.add(div) }); + sel.add(optgroup, function() {}) +}); +</script> +</head> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/window.html b/tests/wpt/mozilla/tests/mozilla/window.html new file mode 100644 index 00000000000..1bc363a1122 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/window.html @@ -0,0 +1,15 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + assert_equals(window, window.self); + assert_true(window.self instanceof Window, "Should be Window"); +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/window_performance.html b/tests/wpt/mozilla/tests/mozilla/window_performance.html new file mode 100644 index 00000000000..6b96c18b3cd --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/window_performance.html @@ -0,0 +1,30 @@ +<html> +<head> + <title></title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +test(function() { + assert_not_equals(window.performance, undefined); + assert_true(window.performance instanceof Performance, "Should be Performance"); + + assert_not_equals(window.performance.timing, undefined); + assert_true(window.performance.timing instanceof PerformanceTiming, "Should be PerformanceTiming"); + + assert_greater_than(window.performance.timing.navigationStart, 0); + + var last = window.performance.now(); + assert_greater_than(last, 0); + + // Check that window.performance.now() is monotonically increasing + for (var i = 0; i < 100; i++) { + var next = window.performance.now(); + assert_greater_than(next, last); + last = next; + } +}); +</script> +</body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/window_setInterval.html b/tests/wpt/mozilla/tests/mozilla/window_setInterval.html new file mode 100644 index 00000000000..a3c68a69b03 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/window_setInterval.html @@ -0,0 +1,22 @@ +<html> + <head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + async_test(function() { + var x = 0; + var intervalID = setInterval(this.step_func(function() { + x += 1; + if (x == 2) { + clearInterval(intervalID); + setTimeout(this.step_func_done(function() { + assert_equals(x, 2); + }), 300); + } + }), 10); + }); + </script> + </body> +</html> diff --git a/tests/wpt/mozilla/tests/mozilla/windowproxy.html b/tests/wpt/mozilla/tests/mozilla/windowproxy.html new file mode 100644 index 00000000000..8ea7fc43392 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/windowproxy.html @@ -0,0 +1,28 @@ +<html> +<head id="foo"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div></div> +<script> +test(function() { + window.abcd = 15; + assert_equals(window.abcd, 15); + assert_equals(Object.getOwnPropertyDescriptor(window, 'abcd').value, 15); + assert_equals(window.hasOwnProperty('abcd'), true); + + assert_equals('location' in window, true); + + // Can't set indexed properties + window[100] = "abc"; + assert_equals(window[100], undefined); + assert_equals(Object.getOwnPropertyDescriptor(window, 1000), undefined); +}); + +test(function() { + assert_own_property(window, 'location') +}, "Unforgeable location"); +</script> +</body> +</html> diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm index 48a9993858c..7cc69765b0f 100644 --- a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm +++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm @@ -2,6 +2,7 @@ <meta charset="utf-8"> <title>IDBObjectStoreParameters</title> <link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal"> +<meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="support.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js index 54142fd6355..056d77c0136 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js @@ -2,14 +2,14 @@ if (this.document === undefined) importScripts("xmlhttprequest-timeout.js"); /* This sets up three requests: -The first request will only be open()ed, not aborted, timeout will be 400 but will never triggered because send() isn't called. -After a 1 second delay, the test asserts that no load/error/timeout/abort events fired +The first request will only be open()ed, not aborted, timeout will be TIME_REGULAR_TIMEOUT but will never triggered because send() isn't called. +After TIME_NORMAL_LOAD, the test asserts that no load/error/timeout/abort events fired Second request will be aborted immediately after send(), test asserts that abort fired -Third request is set up to call abort() after a 1 second delay, but it also has a 400ms timeout. Asserts that timeout fired. -(abort() is called 600ms later and should not fire an abort event per spec. This is untested!) +Third request is set up to call abort() after TIME_NORMAL_LOAD, but it also has a TIME_REGULAR_TIMEOUT timeout. Asserts that timeout fired. +(abort() is called later and should not fire an abort event per spec. This is untested!) */ runTestRequests([ new AbortedRequest(false), - new AbortedRequest(true, -1), - new AbortedRequest(true, TIME_NORMAL_LOAD) ]); + new AbortedRequest(true, -1), + new AbortedRequest(true, TIME_NORMAL_LOAD) ]); diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js index a6a67f1b85f..8dde8ef573e 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js @@ -1,8 +1,8 @@ /* -This test sets up two requests: +This test sets up two requests: one that gets abort()ed from a 0ms timeout (0ms will obviously be clamped to whatever the implementation's minimal value is), asserts abort event fires -one that will be aborted after 200ms (TIME_DELAY), (with a timeout at 400ms) asserts abort event fires. Does not assert that the timeout event does *not* fire. +one that will be aborted after TIME_DELAY, (with a timeout at TIME_REGULAR_TIMEOUT) asserts abort event fires. Does not assert that the timeout event does *not* fire. */ runTestRequests([ new AbortedRequest(true, 0), - new AbortedRequest(true, TIME_DELAY) ]); + new AbortedRequest(true, TIME_DELAY) ]); diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js index 12f5eb5eacc..6dc2173b2e6 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js @@ -2,10 +2,10 @@ if (this.document === undefined) importScripts("xmlhttprequest-timeout.js"); /* Sets up three requests to a resource that will take 0.6 seconds to load: -1) timeout first set to 1000ms, after 400ms timeout is set to 0, asserts load fires -2) timeout first set to 1000ms, after 200ms timeout is set to 400, asserts load fires (race condition..?!?) -3) timeout first set to 0, after 400ms it is set to 1000, asserts load fires +1) timeout first set to TIME_NORMAL_LOAD, after TIME_REGULAR_TIMEOUT timeout is set to 0, asserts load fires +2) timeout first set to TIME_NORMAL_LOAD, after TIME_DELAY timeout is set to TIME_REGULAR_TIMEOUT, asserts load fires (race condition..?!?) +3) timeout first set to 0, after TIME_REGULAR_TIMEOUT it is set to TIME_REGULAR_TIMEOUT * 10, asserts load fires */ runTestRequests([ new RequestTracker(true, "timeout disabled after initially set", TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, 0), - new RequestTracker(true, "timeout overrides load after a delay", TIME_NORMAL_LOAD, TIME_DELAY, TIME_REGULAR_TIMEOUT), - new RequestTracker(true, "timeout enabled after initially disabled", 0, TIME_REGULAR_TIMEOUT, TIME_NORMAL_LOAD * 10) ]); + new RequestTracker(true, "timeout overrides load after a delay", TIME_NORMAL_LOAD, TIME_DELAY, TIME_REGULAR_TIMEOUT), + new RequestTracker(true, "timeout enabled after initially disabled", 0, TIME_REGULAR_TIMEOUT, TIME_NORMAL_LOAD * 10) ]); diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js index 7114dfe0257..bf251fa8053 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js @@ -1,13 +1,12 @@ if (this.document === undefined) importScripts("xmlhttprequest-timeout.js"); /* - Starts three requests: - 1) XHR to resource which will take a least 600ms with timeout initially set to 1000ms. After 800ms timeout is supposedly reset to 200ms, - but the resource should have finished loading already. Asserts "load" fires. - 2) XHR with initial timeout set to 1000, after 400ms sets timeout to 300ms. Asserts "timeout" fires. - (Originally new value was 200ms. Race condition-y. Setting the new timeout to 300ms would be a better test of the "measured from start of fetching" requirement.) - 3) XHR with initial timeout set to 200, after 400ms sets timeout to 500ms. Asserts "timeout" fires (the change happens when timeout already fired and the request is done). + Starts three requests: + 1) XHR to resource which will take a least TIME_XHR_LOAD ms with timeout initially set to TIME_NORMAL_LOAD ms. After TIME_LATE_TIMEOUT ms timeout is supposedly reset to TIME_DELAY ms, + but the resource should have finished loading already. Asserts "load" fires. + 2) XHR with initial timeout set to TIME_NORMAL_LOAD, after TIME_REGULAR_TIMEOUT sets timeout to TIME_DELAY+100. Asserts "timeout" fires. + 3) XHR with initial timeout set to TIME_DELAY, after TIME_REGULAR_TIMEOUT sets timeout to 500ms. Asserts "timeout" fires (the change happens when timeout already fired and the request is done). */ runTestRequests([ new RequestTracker(true, "timeout set to expiring value after load fires", TIME_NORMAL_LOAD, TIME_LATE_TIMEOUT, TIME_DELAY), - new RequestTracker(true, "timeout set to expired value before load fires", TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, TIME_DELAY+100), - new RequestTracker(true, "timeout set to non-expiring value after timeout fires", TIME_DELAY, TIME_REGULAR_TIMEOUT, 500) ]); + new RequestTracker(true, "timeout set to expired value before load fires", TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, TIME_DELAY+100), + new RequestTracker(true, "timeout set to non-expiring value after timeout fires", TIME_DELAY, TIME_REGULAR_TIMEOUT, 500) ]); diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js index 3d92b2ebf4c..151226a94fb 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js @@ -1,3 +1,4 @@ + function testResultCallbackHandler(event) { if (event.data == "done") { done(); @@ -16,5 +17,5 @@ function testResultCallbackHandler(event) { window.addEventListener("message", testResultCallbackHandler); // Setting up testharness.js -setup({ explicit_done: true, timeout: 30 * 1000 }); +setup({ explicit_done: true }); diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js index f3ef49aef63..01e63cde691 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js @@ -11,12 +11,12 @@ request handlers. */ -var TIME_NORMAL_LOAD = 1000; -var TIME_LATE_TIMEOUT = 800; -var TIME_XHR_LOAD = 600; -var TIME_REGULAR_TIMEOUT = 400; -var TIME_SYNC_TIMEOUT = 200; -var TIME_DELAY = 200; +var TIME_NORMAL_LOAD = 5000; +var TIME_LATE_TIMEOUT = 4000; +var TIME_XHR_LOAD = 3000; +var TIME_REGULAR_TIMEOUT = 2000; +var TIME_SYNC_TIMEOUT = 1000; +var TIME_DELAY = 1000; /* * This should point to a resource that responds with a text/plain resource after a delay of TIME_XHR_LOAD milliseconds. diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.html b/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.html new file mode 100644 index 00000000000..1753e5f3a5b --- /dev/null +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>XMLHttpRequest.send(URLSearchParams)</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="send-usp.js"></script> +<div id="log"></div> +<script> +run_test(); +</script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.js b/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.js new file mode 100644 index 00000000000..56e9e09640f --- /dev/null +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.js @@ -0,0 +1,39 @@ +function encode(n) { + if (n === 0x20) { + return "\x2B"; + } + + if (n === 0x2A || n === 0x2D || n === 0x2E || + (0x30 <= n && n <= 0x39) || (0x41 <= n && n <= 0x5A) || + n === 0x5F || (0x61 <= n && n <= 0x7A)) { + return String.fromCharCode(n); + } + + var s = n.toString(16).toUpperCase(); + return "%" + (s.length === 2 ? s : '0' + s); +} + +function do_test(n) { + async_test(function() { + var x = new XMLHttpRequest(); + x.onload = this.step_func_done(function(e) { + assert_equals(x.response, "a=" + encode(n)) + }); + x.onerror = this.unreached_func(); + x.open("POST", "resources/content.py"); + var usp = new URLSearchParams(); + usp.append("a", String.fromCharCode(n)); + x.send(usp) + }, "XMLHttpRequest.send(URLSearchParams) (" + n + ")"); +} + +function run_test() { + var i = 0; + add_result_callback(function() { + if (++i === 128) { + return; + } + do_test(i); + }); + do_test(i); +} diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.worker.js b/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.worker.js new file mode 100644 index 00000000000..7fc3d8e041f --- /dev/null +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-usp.worker.js @@ -0,0 +1,5 @@ +importScripts("/resources/testharness.js"); +importScripts("/resources/testharnessreport.js"); +importScripts("send-usp.js"); +run_test(); +done(); diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html index 2be888f8884..cf639487b2d 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html @@ -12,6 +12,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html index 9226ffadddd..9ce5444d777 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html @@ -8,6 +8,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-abort" data-tested-assertations="../.." /> <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol/li[9]"/> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html index 82fee067c63..6366e311222 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html @@ -8,6 +8,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/> <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html index 260844d0db6..e479a30eeac 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html @@ -9,6 +9,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html index aa473442ee4..e7cf089b1ac 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html @@ -9,6 +9,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html index 992b10efd97..ce2537cbc0b 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html @@ -6,6 +6,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[1]" /> <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[10]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html index 4634220eca4..f29bf9824f5 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html @@ -10,6 +10,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/> <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html index f0005afa2e0..e5dab5a3947 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html @@ -12,6 +12,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout-runner.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html index e3dbd5c949b..c5d37c10f62 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html @@ -8,6 +8,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/> <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout-runner.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html index a2c8009ea74..c1e601dd130 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html @@ -9,6 +9,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout-runner.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html index 994ccb6ecce..1113dfcda97 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html @@ -9,6 +9,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout-runner.js"></script> @@ -19,7 +20,7 @@ <div id="log"></div> <script type="text/javascript"> var worker = new Worker("resources/xmlhttprequest-timeout-simple.js"); - worker.onmessage = testResultCallbackHandler; + worker.onmessage = testResultCallbackHandler; </script> </body> </html> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html index 50aa65193c9..f9c2d3c3ff6 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html @@ -9,6 +9,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout-runner.js"></script> diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html index 18f6a39248a..fdf3646b34a 100644 --- a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html +++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html @@ -9,6 +9,7 @@ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/> <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" /> <link rel="stylesheet" href="/resources/testharness.css" /> + <meta name=timeout content=long> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/xmlhttprequest-timeout-runner.js"></script> diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js index 4fc3bb71c1e..8cd092147cb 100644 --- a/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js +++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js @@ -1,20 +1,20 @@ (function () { - var test = new async_test("test inline worker"); var workerSource = document.getElementById('inlineWorker'); - var blob = new Blob([workerSource.textContent]); // can I create a new script tag like this? ack... var url = window.URL.createObjectURL(blob); - var worker = new Worker(url); + try { + var worker = new Worker(url); + } + catch (e) { + done(); + } worker.addEventListener('message', function(e) { - test.step(function () { - assert_not_equals(e.data, 'fail', 'inline script ran'); - test.done(); - }) + assert_unreached("script ran"); }, false); worker.postMessage(''); diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html b/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html index 3b1bb7e04ff..d429750f76e 100644 --- a/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html +++ b/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html @@ -318,4 +318,17 @@ test(function() { assert_equals(a.firstChild, c); assert_equals(c.parentNode, a); }, "replaceChild should work in the presence of mutation events.") +test(function() { + var TEST_ID = "findme"; + var gBody = document.getElementsByTagName("body")[0]; + var parent = document.createElement("div"); + gBody.appendChild(parent); + var child = document.createElement("div"); + parent.appendChild(child); + var df = document.createDocumentFragment(); + var fragChild = df.appendChild(document.createElement("div")); + fragChild.setAttribute("id", TEST_ID); + parent.replaceChild(df, child); + assert_equals(document.getElementById(TEST_ID), fragChild, "should not be null"); +}, "Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id.") </script> diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html index 843b671534f..3316bf5316f 100644 --- a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html +++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html @@ -42,7 +42,7 @@ var unforgeableAttributes = [ "top" ]; -var replacableAttributes = [ +var replaceableAttributes = [ "self", "locationbar", "menubar", @@ -51,7 +51,23 @@ var replacableAttributes = [ "statusbar", "toolbar", "frames", - "length" + "parent", + "external", + "length", + + // CSSOM-View + "screen", + "scrollX", + "scrollY", + "pageXOffset", + "pageYOffset", + "innerWidth", + "innerHeight", + "screenX", + "screenY", + "outerWidth", + "outerHeight", + "devicePixelRatio", ]; var methods = [ @@ -98,10 +114,8 @@ if ("showModalDialog" in window) { var readonlyAttributes = [ "history", - "parent", "frameElement", "navigator", - "external", "applicationCache", // WindowSessionStorage @@ -109,19 +123,6 @@ var readonlyAttributes = [ // WindowLocalStorage "localStorage", - - // CSSOM-View - "screen", - "innerWidth", - "innerHeight", - "scrollX", - "pageXOffset", - "scrollY", - "pageYOffset", - "screenX", - "screenY", - "outerWidth", - "outerHeight" ]; var writableAttributes = [ @@ -259,8 +260,7 @@ test(function() { assert_equals(window[id], EventTargetProto[id]); assert_data_propdesc(Object.getOwnPropertyDescriptor(EventTargetProto, id), true, true, true); - assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id), - true, true, true); + assert_equals(Object.getOwnPropertyDescriptor(window, id), undefined); }, "EventTarget method: " + id); }); }, "EventTarget interface"); @@ -303,7 +303,7 @@ test(function() { id === "location", true, false); }, "Window unforgeable attribute: " + id); }); - replacableAttributes.forEach(function(id) { + replaceableAttributes.forEach(function(id) { test(function() { var WindowProto = Window.prototype; assert_true(id in window, id + " in window"); diff --git a/tests/wpt/web-platform-tests/html/dom/elements-misc.js b/tests/wpt/web-platform-tests/html/dom/elements-misc.js index b495d83d4ce..77cc4cd729a 100644 --- a/tests/wpt/web-platform-tests/html/dom/elements-misc.js +++ b/tests/wpt/web-platform-tests/html/dom/elements-misc.js @@ -50,6 +50,9 @@ var miscElements = { radiogroup: "string", "default": "boolean", }, + dialog: { + open: "boolean", + }, // Global attributes should exist even on unknown elements undefinedelement: {}, diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html new file mode 100644 index 00000000000..f1679e2809a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-select-event-manual.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>HTMLTextAreaElement Test: select event</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<meta name="flags" content="interact"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<p>Select any numberic characters in the text area below</p> + +<form id="testForm" name="testForm"> + <textarea id="testtextarea">0123456789</textarea> +</form> + +<script> + +var textarea = document.getElementById("testtextarea"); + +setup({explicit_done : true}); +setup({explicit_timeout : true}); + +on_event(textarea, "select", function(evt) { + test(function() { + assert_greater_than(textarea.value.substring(textarea.selectionStart, textarea.selectionEnd).length, 0, "Check if select event captured when text selected"); + }); + done(); +}); + +</script> + +<div id="log"></div> diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html new file mode 100644 index 00000000000..4e98ba5093a --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-select-manual.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>HTMLTextAreaElement Test: select()</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<meta name="flags" content="interact"> + +<p>Test passes if content of the input area is selected</p> + +<textarea id="test_obj">1234567</textarea> +<script> +var textarea = document.querySelector("#test_obj"); +textarea.select(); +</script> diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html index d6e92c0732d..c9e990206fe 100644 --- a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html +++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html @@ -15,7 +15,7 @@ var script=testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&'+Math.random() }, document.getElementsByTagName('head')[0], false ); log('end script #1'); </script> - <script src="scripts/include-2.js?pipe=trickle(d2)"></script> + <script src="scripts/include-2.js?pipe=trickle(d4)"></script> <script type="text/javascript"> var t = async_test() diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/common.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/common.https.html new file mode 100644 index 00000000000..6164290dea1 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/common.https.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<title>Cache Storage: Verify that Window and Workers see same storage</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script> + +function wait_for_message(worker) { + return new Promise(function(resolve) { + worker.addEventListener('message', function listener(e) { + resolve(e.data); + worker.removeEventListener('message', listener); + }); + }); +} + +promise_test(function(t) { + var cache_name = 'common-test'; + return self.caches.delete(cache_name) + .then(function() { + var worker = new Worker('resources/common-worker.js'); + worker.postMessage({name: cache_name}); + return wait_for_message(worker); + }) + .then(function(message) { + return self.caches.open(cache_name); + }) + .then(function(cache) { + return Promise.all([ + cache.match('https://example.com/a'), + cache.match('https://example.com/b'), + cache.match('https://example.com/c') + ]); + }) + .then(function(responses) { + return Promise.all(responses.map( + function(response) { return response.text(); } + )); + }) + .then(function(bodies) { + assert_equals(bodies[0], 'a', + 'Body should match response put by worker'); + assert_equals(bodies[1], 'b', + 'Body should match response put by worker'); + assert_equals(bodies[2], 'c', + 'Body should match response put by worker'); + }); +}, 'Window sees cache puts by Worker'); + +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/blank.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/blank.html new file mode 100644 index 00000000000..a3c3a4689a6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/blank.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<title>Empty doc</title> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/common-worker.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/common-worker.js new file mode 100644 index 00000000000..d0e8544b56c --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/common-worker.js @@ -0,0 +1,15 @@ +self.onmessage = function(e) { + var cache_name = e.data.name; + + self.caches.open(cache_name) + .then(function(cache) { + return Promise.all([ + cache.put('https://example.com/a', new Response('a')), + cache.put('https://example.com/b', new Response('b')), + cache.put('https://example.com/c', new Response('c')) + ]); + }) + .then(function() { + self.postMessage('ok'); + }); +}; diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/fetch-status.py b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/fetch-status.py new file mode 100644 index 00000000000..71f13ebc3a5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/fetch-status.py @@ -0,0 +1,2 @@ +def main(request, response): + return int(request.GET["status"]), [], "" diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/iframe.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/iframe.html new file mode 100644 index 00000000000..f4f418b8ddb --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/iframe.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>ok</title> +<script> +window.onmessage = function(e) { + var id = e.data.id; + try { + self.caches; + window.parent.postMessage({id: id, result: 'allowed'}, '*'); + } catch (e) { + window.parent.postMessage({id: id, result: 'denied', name: e.name, message: e.message}, '*'); + } +}; +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/simple.txt b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/simple.txt new file mode 100644 index 00000000000..9e3cb91fb9b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/simple.txt @@ -0,0 +1 @@ +a simple text file diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/test-helpers.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/test-helpers.js new file mode 100644 index 00000000000..91110950d56 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/test-helpers.js @@ -0,0 +1,37 @@ +(function() { + var next_cache_index = 1; + + // Returns a promise that resolves to a newly created Cache object. The + // returned Cache will be destroyed when |test| completes. + function create_temporary_cache(test) { + var uniquifier = String(++next_cache_index); + var cache_name = self.location.pathname + '/' + uniquifier; + + test.add_cleanup(function() { + self.caches.delete(cache_name); + }); + + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }); + } + + self.create_temporary_cache = create_temporary_cache; +})(); + +// Runs |test_function| with a temporary unique Cache passed in as the only +// argument. The function is run as a part of Promise chain owned by +// promise_test(). As such, it is expected to behave in a manner identical (with +// the exception of the argument) to a function passed into promise_test(). +// +// E.g.: +// cache_test(function(cache) { +// // Do something with |cache|, which is a Cache object. +// }, "Some Cache test"); +function cache_test(test_function, description) { + promise_test(function(test) { + return create_temporary_cache(test) + .then(test_function); + }, description); +} diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/testharness-helpers.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/testharness-helpers.js new file mode 100644 index 00000000000..4d7af1ff9ca --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/resources/testharness-helpers.js @@ -0,0 +1,163 @@ +/* + * testharness-helpers contains various useful extensions to testharness.js to + * allow them to be used across multiple tests before they have been + * upstreamed. This file is intended to be usable from both document and worker + * environments, so code should for example not rely on the DOM. + */ + +// Returns a promise that fulfills after the provided |promise| is fulfilled. +// The |test| succeeds only if |promise| rejects with an exception matching +// |code|. Accepted values for |code| follow those accepted for assert_throws(). +// The optional |description| describes the test being performed. +// +// E.g.: +// assert_promise_rejects( +// new Promise(...), // something that should throw an exception. +// 'NotFoundError', +// 'Should throw NotFoundError.'); +// +// assert_promise_rejects( +// new Promise(...), +// new TypeError(), +// 'Should throw TypeError'); +function assert_promise_rejects(promise, code, description) { + return promise.then( + function() { + throw 'assert_promise_rejects: ' + description + ' Promise did not reject.'; + }, + function(e) { + if (code !== undefined) { + assert_throws(code, function() { throw e; }, description); + } + }); +} + +// Asserts that two objects |actual| and |expected| are weakly equal under the +// following definition: +// +// |a| and |b| are weakly equal if any of the following are true: +// 1. If |a| is not an 'object', and |a| === |b|. +// 2. If |a| is an 'object', and all of the following are true: +// 2.1 |a.p| is weakly equal to |b.p| for all own properties |p| of |a|. +// 2.2 Every own property of |b| is an own property of |a|. +// +// This is a replacement for the the version of assert_object_equals() in +// testharness.js. The latter doesn't handle own properties correctly. I.e. if +// |a.p| is not an own property, it still requires that |b.p| be an own +// property. +// +// Note that |actual| must not contain cyclic references. +self.assert_object_equals = function(actual, expected, description) { + var object_stack = []; + + function _is_equal(actual, expected, prefix) { + if (typeof actual !== 'object') { + assert_equals(actual, expected, prefix); + return; + } + assert_true(typeof expected === 'object', prefix); + assert_equals(object_stack.indexOf(actual), -1, + prefix + ' must not contain cyclic references.'); + + object_stack.push(actual); + + Object.getOwnPropertyNames(expected).forEach(function(property) { + assert_own_property(actual, property, prefix); + _is_equal(actual[property], expected[property], + prefix + '.' + property); + }); + Object.getOwnPropertyNames(actual).forEach(function(property) { + assert_own_property(expected, property, prefix); + }); + + object_stack.pop(); + } + + function _brand(object) { + return Object.prototype.toString.call(object).match(/^\[object (.*)\]$/)[1]; + } + + _is_equal(actual, expected, + (description ? description + ': ' : '') + _brand(expected)); +}; + +// Equivalent to assert_in_array, but uses a weaker equivalence relation +// (assert_object_equals) than '==='. +function assert_object_in_array(actual, expected_array, description) { + assert_true(expected_array.some(function(element) { + try { + assert_object_equals(actual, element); + return true; + } catch (e) { + return false; + } + }), description); +} + +// Assert that the two arrays |actual| and |expected| contain the same set of +// elements as determined by assert_object_equals. The order is not significant. +// +// |expected| is assumed to not contain any duplicates as determined by +// assert_object_equals(). +function assert_array_equivalent(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + expected.forEach(function(expected_element) { + // assert_in_array treats the first argument as being 'actual', and the + // second as being 'expected array'. We are switching them around because + // we want to be resilient against the |actual| array containing + // duplicates. + assert_object_in_array(expected_element, actual, description); + }); +} + +// Asserts that two arrays |actual| and |expected| contain the same set of +// elements as determined by assert_object_equals(). The corresponding elements +// must occupy corresponding indices in their respective arrays. +function assert_array_objects_equals(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + actual.forEach(function(value, index) { + assert_object_equals(value, expected[index], + description + ' : object[' + index + ']'); + }); +} + +// Asserts that |object| that is an instance of some interface has the attribute +// |attribute_name| following the conditions specified by WebIDL, but it's +// acceptable that the attribute |attribute_name| is an own property of the +// object because we're in the middle of moving the attribute to a prototype +// chain. Once we complete the transition to prototype chains, +// assert_will_be_idl_attribute must be replaced with assert_idl_attribute +// defined in testharness.js. +// +// FIXME: Remove assert_will_be_idl_attribute once we complete the transition +// of moving the DOM attributes to prototype chains. (http://crbug.com/43394) +function assert_will_be_idl_attribute(object, attribute_name, description) { + assert_true(typeof object === "object", description); + + assert_true("hasOwnProperty" in object, description); + + // Do not test if |attribute_name| is not an own property because + // |attribute_name| is in the middle of the transition to a prototype + // chain. (http://crbug.com/43394) + + assert_true(attribute_name in object, description); +} + +// Stringifies a DOM object. This function stringifies not only own properties +// but also DOM attributes which are on a prototype chain. Note that +// JSON.stringify only stringifies own properties. +function stringifyDOMObject(object) +{ + function deepCopy(src) { + if (typeof src != "object") + return src; + var dst = Array.isArray(src) ? [] : {}; + for (var property in src) { + dst[property] = deepCopy(src[property]); + } + return dst; + } + return JSON.stringify(deepCopy(object)); +} diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-add.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-add.js new file mode 100644 index 00000000000..3e827382bd1 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-add.js @@ -0,0 +1,145 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +cache_test(function(cache) { + return assert_promise_rejects( + cache.add(), + new TypeError(), + 'Cache.add should throw a TypeError when no arguments are given.'); + }, 'Cache.add called with no arguments'); + +cache_test(function(cache) { + return cache.add('../resources/simple.txt') + .then(function(result) { + assert_equals(result, undefined, + 'Cache.add should resolve with undefined on success.'); + }); + }, 'Cache.add called with relative URL specified as a string'); + +cache_test(function(cache) { + return assert_promise_rejects( + cache.add('javascript://this-is-not-http-mmkay'), + 'NetworkError', + 'Cache.add should throw a NetworkError for non-HTTP/HTTPS URLs.'); + }, 'Cache.add called with non-HTTP/HTTPS URL'); + +cache_test(function(cache) { + var request = new Request('../resources/simple.txt', {method: 'POST', body: 'Hello'}); + return cache.add(request) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.add should resolve with undefined on success.'); + }); + }, 'Cache.add called with Request object'); + +cache_test(function(cache) { + var request = new Request('../resources/simple.txt', {method: 'POST', body: 'Hello'}); + return request.text() + .then(function() { + assert_false(request.bodyUsed); + }) + .then(function() { + return cache.add(request); + }); + }, 'Cache.add called with Request object with a used body'); + +cache_test(function(cache) { + var request = new Request('../resources/simple.txt', {method: 'POST', body: 'Hello'}); + return cache.add(request) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.add should resolve with undefined on success.'); + }) + .then(function() { + return assert_promise_rejects( + cache.add(request), + new TypeError(), + 'Cache.add should throw TypeError if same request is added twice.'); + }); + }, 'Cache.add called twice with the same Request object'); + +cache_test(function(cache) { + return cache.add('this-does-not-exist-please-dont-create-it') + .then(function(result) { + assert_equals(result, undefined, + 'Cache.add should resolve with undefined on success.'); + }); + }, 'Cache.add with request that results in a status of 404'); + +cache_test(function(cache) { + return cache.add('../resources/fetch-status.py?status=500') + .then(function(result) { + assert_equals(result, undefined, + 'Cache.add should resolve with undefined on success.'); + }); + }, 'Cache.add with request that results in a status of 500'); + +cache_test(function(cache) { + return assert_promise_rejects( + cache.addAll(), + new TypeError(), + 'Cache.addAll with no arguments should throw TypeError.'); + }, 'Cache.addAll with no arguments'); + +cache_test(function(cache) { + // Assumes the existence of ../resources/simple.txt and ../resources/blank.html + var urls = ['../resources/simple.txt', undefined, '../resources/blank.html']; + return assert_promise_rejects( + cache.addAll(), + new TypeError(), + 'Cache.addAll should throw TypeError for an undefined argument.'); + }, 'Cache.addAll with a mix of valid and undefined arguments'); + +cache_test(function(cache) { + // Assumes the existence of ../resources/simple.txt and ../resources/blank.html + var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html']; + return cache.addAll(urls) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.addAll should resolve with undefined on ' + + 'success.'); + }); + }, 'Cache.addAll with string URL arguments'); + +cache_test(function(cache) { + // Assumes the existence of ../resources/simple.txt and ../resources/blank.html + var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html']; + var requests = urls.map(function(url) { + return new Request(url); + }); + return cache.addAll(requests) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.addAll should resolve with undefined on ' + + 'success.'); + }); + }, 'Cache.addAll with Request arguments'); + +cache_test(function(cache) { + // Assumes that ../resources/simple.txt and ../resources/blank.html exist. The second + // resource does not. + var urls = ['../resources/simple.txt', 'this-resource-should-not-exist', '../resources/blank.html']; + var requests = urls.map(function(url) { + return new Request(url); + }); + return cache.addAll(requests) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.addAll should resolve with undefined on ' + + 'success.'); + }); + }, 'Cache.addAll with a mix of succeeding and failing requests'); + +cache_test(function(cache) { + var request = new Request('../resources/simple.txt'); + return assert_promise_rejects( + cache.addAll([request, request]), + new TypeError(), + 'Cache.addAll should throw TypeError if the same request is added ' + + 'twice.'); + }, 'Cache.addAll called with the same Request object specified twice'); + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-delete.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-delete.js new file mode 100644 index 00000000000..36ca8473164 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-delete.js @@ -0,0 +1,120 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +var test_url = 'https://example.com/foo'; + +// Construct a generic Request object. The URL is |test_url|. All other fields +// are defaults. +function new_test_request() { + return new Request(test_url); +} + +// Construct a generic Response object. +function new_test_response() { + return new Response('Hello world!', { status: 200 }); +} + +cache_test(function(cache) { + return assert_promise_rejects( + cache.delete(), + new TypeError(), + 'Cache.delete should reject with a TypeError when called with no ' + + 'arguments.'); + }, 'Cache.delete with no arguments'); + +cache_test(function(cache) { + return cache.put(new_test_request(), new_test_response()) + .then(function() { + return cache.delete(test_url); + }) + .then(function(result) { + assert_true(result, + 'Cache.delete should resolve with "true" if an entry ' + + 'was successfully deleted.'); + return cache.match(test_url); + }) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.delete should remove matching entries from cache.'); + }); + }, 'Cache.delete called with a string URL'); + +cache_test(function(cache) { + var request = new Request(test_url, { method: 'POST', body: 'Abc' }); + return cache.put(request.clone(), new_test_response()) + .then(function() { + return cache.delete(request); + }) + .then(function(result) { + assert_true(result, + 'Cache.delete should resolve with "true" if an entry ' + + 'was successfully deleted.'); + assert_false(request.bodyUsed, + 'Cache.delete should not consume request body.'); + }); + }, 'Cache.delete called with a Request object'); + +cache_test(function(cache) { + var request = new Request(test_url, { method: 'POST', body: 'Abc' }); + return cache.put(request.clone(), new_test_response()) + .then(function() { + return request.text(); + }) + .then(function() { + assert_true(request.bodyUsed, + '[https://fetch.spec.whatwg.org/#body-mixin] ' + + 'Request.bodyUsed should be true after text() method ' + + 'resolves.'); + }) + .then(function() { + return cache.delete(request); + }) + .then(function(result) { + assert_true(result, + 'Cache.delete should resolve with "true" if an entry ' + + 'was successfully deleted.'); + }); + }, 'Cache.delete with a Request object containing used body'); + +cache_test(function(cache) { + return cache.delete(test_url) + .then(function(result) { + assert_false(result, + 'Cache.delete should resolve with "false" if there ' + + 'are no matching entries.'); + }); + }, 'Cache.delete with a non-existent entry'); + +var cache_entries = { + a: { + request: new Request('http://example.com/abc'), + response: new Response('') + }, + + b: { + request: new Request('http://example.com/b'), + response: new Response('') + }, + + a_with_query: { + request: new Request('http://example.com/abc?q=r'), + response: new Response('') + } +}; + +function prepopulated_cache_test(test_function, description) { + cache_test(function(cache) { + return Promise.all(Object.keys(cache_entries).map(function(k) { + return cache.put(cache_entries[k].request.clone(), + cache_entries[k].response.clone()); + })) + .then(function() { + return test_function(cache); + }); + }, description); +} + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js new file mode 100644 index 00000000000..4a027b6f165 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js @@ -0,0 +1,501 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +// A set of Request/Response pairs to be used with prepopulated_cache_test(). +var simple_entries = [ + { + name: 'a', + request: new Request('http://example.com/a'), + response: new Response('') + }, + + { + name: 'b', + request: new Request('http://example.com/b'), + response: new Response('') + }, + + { + name: 'a_with_query', + request: new Request('http://example.com/a?q=r'), + response: new Response('') + }, + + { + name: 'A', + request: new Request('http://example.com/A'), + response: new Response('') + }, + + { + name: 'a_https', + request: new Request('https://example.com/a'), + response: new Response('') + }, + + { + name: 'a_org', + request: new Request('http://example.org/a'), + response: new Response('') + }, + + { + name: 'cat', + request: new Request('http://example.com/cat'), + response: new Response('') + }, + + { + name: 'catmandu', + request: new Request('http://example.com/catmandu'), + response: new Response('') + }, + + { + name: 'cat_num_lives', + request: new Request('http://example.com/cat?lives=9'), + response: new Response('') + }, + + { + name: 'cat_in_the_hat', + request: new Request('http://example.com/cat/in/the/hat'), + response: new Response('') + }, + + { + name: 'secret_cat', + request: new Request('http://tom:jerry@example.com/cat'), + response: new Response('') + }, + + { + name: 'top_secret_cat', + request: new Request('http://tom:j3rry@example.com/cat'), + response: new Response('') + } +]; + +// A set of Request/Response pairs to be used with prepopulated_cache_test(). +// These contain a mix of test cases that use Vary headers. +var vary_entries = [ + { + name: 'vary_cookie_is_cookie', + request: new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}), + response: new Response('', + {headers: {'Vary': 'Cookies'}}) + }, + + { + name: 'vary_cookie_is_good', + request: new Request('http://example.com/c', + {headers: {'Cookies': 'is-good-enough-for-me'}}), + response: new Response('', + {headers: {'Vary': 'Cookies'}}) + }, + + { + name: 'vary_cookie_absent', + request: new Request('http://example.com/c'), + response: new Response('', + {headers: {'Vary': 'Cookies'}}) + }, + + { + name: 'vary_wildcard', + request: new Request('http://example.com/c', + {headers: {'Cookies': 'x', 'X-Key': '1'}}), + response: new Response('', + {headers: {'Vary': '*'}}) + } +]; + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll('not-present-in-the-cache') + .then(function(result) { + assert_array_equivalent( + result, [], + 'Cache.matchAll should resolve with an empty array on failure.'); + }); + }, 'Cache.matchAll with no matching entries'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match('not-present-in-the-cache') + .then(function(result) { + assert_equals(result, undefined, + 'Cache.match failures should resolve with undefined.'); + }); + }, 'Cache.match with no matching entries'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a.request.url) + .then(function(result) { + assert_array_objects_equals(result, [entries.a.response], + 'Cache.matchAll should match by URL.'); + }); + }, 'Cache.matchAll with URL'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(entries.a.request.url) + .then(function(result) { + assert_object_equals(result, entries.a.response, + 'Cache.match should match by URL.'); + }); + }, 'Cache.match with URL'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a.request) + .then(function(result) { + assert_array_objects_equals( + result, [entries.a.response], + 'Cache.matchAll should match by Request.'); + }); + }, 'Cache.matchAll with Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(entries.a.request) + .then(function(result) { + assert_object_equals(result, entries.a.response, + 'Cache.match should match by Request.'); + }); + }, 'Cache.match with Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(new Request(entries.a.request.url)) + .then(function(result) { + assert_array_objects_equals( + result, [entries.a.response], + 'Cache.matchAll should match by Request.'); + }); + }, 'Cache.matchAll with new Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(new Request(entries.a.request.url)) + .then(function(result) { + assert_object_equals(result, entries.a.response, + 'Cache.match should match by Request.'); + }); + }, 'Cache.match with new Request'); + +cache_test(function(cache) { + var request = new Request('https://example.com/foo', { + method: 'POST', + body: 'Hello world!' + }); + var response = new Response('Booyah!', { + status: 200, + headers: {'Content-Type': 'text/plain'} + }); + + return cache.put(request.clone(), response.clone()) + .then(function() { + assert_false( + request.bodyUsed, + '[https://fetch.spec.whatwg.org/#concept-body-used-flag] ' + + 'Request.bodyUsed flag should be initially false.'); + }) + .then(function() { + return cache.match(request); + }) + .then(function(result) { + assert_false(request.bodyUsed, + 'Cache.match should not consume Request body.'); + }); + }, 'Cache.match with Request containing non-empty body'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a.request, + {ignoreSearch: true}) + .then(function(result) { + assert_array_equivalent( + result, + [ + entries.a.response, + entries.a_with_query.response + ], + 'Cache.matchAll with ignoreSearch should ignore the ' + + 'search parameters of cached request.'); + }); + }, + 'Cache.matchAll with ignoreSearch option (request with no search ' + + 'parameters)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(entries.a.request, + {ignoreSearch: true}) + .then(function(result) { + assert_object_in_array( + result, + [ + entries.a.response, + entries.a_with_query.response + ], + 'Cache.match with ignoreSearch should ignore the ' + + 'search parameters of cached request.'); + }); + }, + 'Cache.match with ignoreSearch option (request with no search ' + + 'parameters)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a_with_query.request, + {ignoreSearch: true}) + .then(function(result) { + assert_array_equivalent( + result, + [ + entries.a.response, + entries.a_with_query.response + ], + 'Cache.matchAll with ignoreSearch should ignore the ' + + 'search parameters of request.'); + }); + }, + 'Cache.matchAll with ignoreSearch option (request with search parameter)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(entries.a_with_query.request, + {ignoreSearch: true}) + .then(function(result) { + assert_object_in_array( + result, + [ + entries.a.response, + entries.a_with_query.response + ], + 'Cache.match with ignoreSearch should ignore the ' + + 'search parameters of request.'); + }); + }, + 'Cache.match with ignoreSearch option (request with search parameter)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.cat.request.url + '#mouse') + .then(function(result) { + assert_array_equivalent( + result, + [ + entries.cat.response, + ], + 'Cache.matchAll should ignore URL fragment.'); + }); + }, 'Cache.matchAll with URL containing fragment'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(entries.cat.request.url + '#mouse') + .then(function(result) { + assert_object_equals(result, entries.cat.response, + 'Cache.match should ignore URL fragment.'); + }); + }, 'Cache.match with URL containing fragment'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll('http') + .then(function(result) { + assert_array_equivalent( + result, [], + 'Cache.matchAll should treat query as a URL and not ' + + 'just a string fragment.'); + }); + }, 'Cache.matchAll with string fragment "http" as query'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match('http') + .then(function(result) { + assert_equals( + result, undefined, + 'Cache.match should treat query as a URL and not ' + + 'just a string fragment.'); + }); + }, 'Cache.match with string fragment "http" as query'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.secret_cat.request.url) + .then(function(result) { + assert_array_equivalent( + result, [entries.secret_cat.response], + 'Cache.matchAll should not ignore embedded credentials'); + }); + }, 'Cache.matchAll with URL containing credentials'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.match(entries.secret_cat.request.url) + .then(function(result) { + assert_object_equals( + result, entries.secret_cat.response, + 'Cache.match should not ignore embedded credentials'); + }); + }, 'Cache.match with URL containing credentials'); + +prepopulated_cache_test(vary_entries, function(cache, entries) { + return cache.matchAll('http://example.com/c') + .then(function(result) { + assert_array_equivalent( + result, + [ + entries.vary_wildcard.response, + entries.vary_cookie_absent.response + ], + 'Cache.matchAll should exclude matches if a vary header is ' + + 'missing in the query request, but is present in the cached ' + + 'request.'); + }) + + .then(function() { + return cache.matchAll( + new Request('http://example.com/c', + {headers: {'Cookies': 'none-of-the-above'}})); + }) + .then(function(result) { + assert_array_equivalent( + result, + [ + entries.vary_wildcard.response + ], + 'Cache.matchAll should exclude matches if a vary header is ' + + 'missing in the cached request, but is present in the query ' + + 'request.'); + }) + + .then(function() { + return cache.matchAll( + new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}})); + }) + .then(function(result) { + assert_array_equivalent( + result, + [entries.vary_cookie_is_cookie.response], + 'Cache.matchAll should match the entire header if a vary header ' + + 'is present in both the query and cached requests.'); + }); + }, 'Cache.matchAll with responses containing "Vary" header'); + +prepopulated_cache_test(vary_entries, function(cache, entries) { + return cache.match('http://example.com/c') + .then(function(result) { + assert_object_in_array( + result, + [ + entries.vary_wildcard.response, + entries.vary_cookie_absent.response + ], + 'Cache.match should honor "Vary" header.'); + }); + }, 'Cache.match with responses containing "Vary" header'); + +prepopulated_cache_test(vary_entries, function(cache, entries) { + return cache.matchAll('http://example.com/c', + {ignoreVary: true}) + .then(function(result) { + assert_array_equivalent( + result, + [ + entries.vary_cookie_is_cookie.response, + entries.vary_cookie_is_good.response, + entries.vary_cookie_absent.response, + entries.vary_wildcard.response + ], + 'Cache.matchAll should honor "ignoreVary" parameter.'); + }); + }, 'Cache.matchAll with "ignoreVary" parameter'); + +cache_test(function(cache) { + var request = new Request('http://example.com'); + var response; + var request_url = new URL('../resources/simple.txt', location.href).href; + return fetch(request_url) + .then(function(fetch_result) { + response = fetch_result; + assert_equals( + response.url, request_url, + '[https://fetch.spec.whatwg.org/#dom-response-url] ' + + 'Reponse.url should return the URL of the response.'); + return cache.put(request, response.clone()); + }) + .then(function() { + return cache.match(request.url); + }) + .then(function(result) { + assert_object_equals( + result, response, + 'Cache.match should return a Response object that has the same ' + + 'properties as the stored response.'); + return cache.match(response.url); + }) + .then(function(result) { + assert_equals( + result, undefined, + 'Cache.match should not match cache entry based on response URL.'); + }); + }, 'Cache.match with Request and Response objects with different URLs'); + +cache_test(function(cache) { + var request_url = new URL('../resources/simple.txt', location.href).href; + return fetch(request_url) + .then(function(fetch_result) { + return cache.put(new Request(request_url), fetch_result); + }) + .then(function() { + return cache.match(request_url); + }) + .then(function(result) { + return result.text(); + }) + .then(function(body_text) { + assert_equals(body_text, 'a simple text file\n', + 'Cache.match should return a Response object with a ' + + 'valid body.'); + }) + .then(function() { + return cache.match(request_url); + }) + .then(function(result) { + return result.text(); + }) + .then(function(body_text) { + assert_equals(body_text, 'a simple text file\n', + 'Cache.match should return a Response object with a ' + + 'valid body each time it is called.'); + }); + }, 'Cache.match invoked multiple times for the same Request/Response'); + +// Helpers --- + +// Run |test_function| with a Cache object as its only parameter. Prior to the +// call, the Cache is populated by cache entries from |entries|. The latter is +// expected to be an Object mapping arbitrary keys to objects of the form +// {request: <Request object>, response: <Response object>}. There's no +// guarantee on the order in which entries will be added to the cache. +// +// |test_function| should return a Promise that can be used with promise_test. +function prepopulated_cache_test(entries, test_function, description) { + cache_test(function(cache) { + var p = Promise.resolve(); + var hash = {}; + entries.forEach(function(entry) { + p = p.then(function() { + return cache.put(entry.request.clone(), + entry.response.clone()) + .catch(function(e) { + assert_unreached('Test setup failed for entry ' + + entry.name + ': ' + e); + }); + }); + hash[entry.name] = entry; + }); + p = p.then(function() { + assert_equals(Object.keys(hash).length, entries.length); + }); + + return p.then(function() { + return test_function(cache, hash); + }); + }, description); +} + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-put.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-put.js new file mode 100644 index 00000000000..ec1617f04e9 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-put.js @@ -0,0 +1,324 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +var test_url = 'https://example.com/foo'; +var test_body = 'Hello world!'; + +cache_test(function(cache) { + var request = new Request(test_url); + var response = new Response(test_body); + return cache.put(request, response) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.put should resolve with undefined on success.'); + }); + }, 'Cache.put called with simple Request and Response'); + +cache_test(function(cache) { + var test_url = new URL('../resources/simple.txt', location.href).href; + var request = new Request(test_url); + var response; + return fetch(test_url) + .then(function(fetch_result) { + response = fetch_result.clone(); + return cache.put(request, fetch_result); + }) + .then(function() { + return cache.match(test_url); + }) + .then(function(result) { + assert_object_equals(result, response, + 'Cache.put should update the cache with ' + + 'new request and response.'); + return result.text(); + }) + .then(function(body) { + assert_equals(body, 'a simple text file\n', + 'Cache.put should store response body.'); + }); + }, 'Cache.put called with Request and Response from fetch()'); + +cache_test(function(cache) { + var request = new Request(test_url); + var response = new Response(test_body); + assert_false(request.bodyUsed, + '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + + 'Request.bodyUsed should be initially false.'); + return cache.put(request, response) + .then(function() { + assert_false(request.bodyUsed, + 'Cache.put should not mark empty request\'s body used'); + }); + }, 'Cache.put with Request without a body'); + +cache_test(function(cache) { + var request = new Request(test_url); + var response = new Response(); + assert_false(response.bodyUsed, + '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + + 'Response.bodyUsed should be initially false.'); + return cache.put(request, response) + .then(function() { + assert_false(response.bodyUsed, + 'Cache.put should not mark empty response\'s body used'); + }); + }, 'Cache.put with Response without a body'); + +cache_test(function(cache) { + var request = new Request(test_url, { + method: 'POST', + body: 'Hello' + }); + var response = new Response(test_body); + assert_false(request.bodyUsed, + '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + + 'Request.bodyUsed should be initially false.'); + return cache.put(request, response.clone()) + .then(function() { + assert_true(request.bodyUsed, + 'Cache.put should consume Request body.'); + }) + .then(function() { + return cache.match(request); + }) + .then(function(result) { + assert_object_equals(result, response, + 'Cache.put should store response body.'); + }); + }, 'Cache.put with Request containing a body'); + +cache_test(function(cache) { + var request = new Request(test_url); + var response = new Response(test_body); + return cache.put(request, response.clone()) + .then(function() { + return cache.match(test_url); + }) + .then(function(result) { + assert_object_equals(result, response, + 'Cache.put should update the cache with ' + + 'new Request and Response.'); + }); + }, 'Cache.put with a Response containing an empty URL'); + +cache_test(function(cache) { + var request = new Request(test_url); + var response = new Response('', { + status: 200, + headers: [['Content-Type', 'text/plain']] + }); + return cache.put(request, response) + .then(function() { + return cache.match(test_url); + }) + .then(function(result) { + assert_equals(result.status, 200, 'Cache.put should store status.'); + assert_equals(result.headers.get('Content-Type'), 'text/plain', + 'Cache.put should store headers.'); + return result.text(); + }) + .then(function(body) { + assert_equals(body, '', + 'Cache.put should store response body.'); + }); + }, 'Cache.put with an empty response body'); + +cache_test(function(cache) { + var test_url = new URL('../resources/fetch-status.py?status=500', location.href).href; + var request = new Request(test_url); + var response; + return fetch(test_url) + .then(function(fetch_result) { + assert_equals(fetch_result.status, 500, + 'Test framework error: The status code should be 500.'); + response = fetch_result.clone(); + return cache.put(request, fetch_result); + }) + .then(function() { + return cache.match(test_url); + }) + .then(function(result) { + assert_object_equals(result, response, + 'Cache.put should update the cache with ' + + 'new request and response.'); + return result.text(); + }) + .then(function(body) { + assert_equals(body, '', + 'Cache.put should store response body.'); + }); + }, 'Cache.put with HTTP 500 response'); + +cache_test(function(cache) { + var alternate_response_body = 'New body'; + var alternate_response = new Response(alternate_response_body, + { statusText: 'New status' }); + return cache.put(new Request(test_url), + new Response('Old body', { statusText: 'Old status' })) + .then(function() { + return cache.put(new Request(test_url), alternate_response.clone()); + }) + .then(function() { + return cache.match(test_url); + }) + .then(function(result) { + assert_object_equals(result, alternate_response, + 'Cache.put should replace existing ' + + 'response with new response.'); + return result.text(); + }) + .then(function(body) { + assert_equals(body, alternate_response_body, + 'Cache put should store new response body.'); + }); + }, 'Cache.put called twice with matching Requests and different Responses'); + +cache_test(function(cache) { + var first_url = test_url; + var second_url = first_url + '#(O_o)'; + var alternate_response_body = 'New body'; + var alternate_response = new Response(alternate_response_body, + { statusText: 'New status' }); + return cache.put(new Request(first_url), + new Response('Old body', { statusText: 'Old status' })) + .then(function() { + return cache.put(new Request(second_url), alternate_response.clone()); + }) + .then(function() { + return cache.match(test_url); + }) + .then(function(result) { + assert_object_equals(result, alternate_response, + 'Cache.put should replace existing ' + + 'response with new response.'); + return result.text(); + }) + .then(function(body) { + assert_equals(body, alternate_response_body, + 'Cache put should store new response body.'); + }); + }, 'Cache.put called twice with request URLs that differ only by a fragment'); + +cache_test(function(cache) { + var entries = { + dark: { + url: 'http://darkhelmet:12345@example.com/spaceballs', + body: 'Moranis' + }, + + skroob: { + url: 'http://skroob:12345@example.com/spaceballs', + body: 'Brooks' + }, + + control: { + url: 'http://example.com/spaceballs', + body: 'v(o.o)v' + } + }; + + return Promise.all(Object.keys(entries).map(function(key) { + return cache.put(new Request(entries[key].url), + new Response(entries[key].body)); + })) + .then(function() { + return Promise.all(Object.keys(entries).map(function(key) { + return cache.match(entries[key].url) + .then(function(result) { + return result.text(); + }) + .then(function(body) { + assert_equals(body, entries[key].body, + 'Cache put should store response body.'); + }); + })); + }); + }, 'Cache.put with request URLs containing embedded credentials'); + +cache_test(function(cache) { + var url = 'http://example.com/foo'; + return cache.put(url, new Response('some body')) + .then(function() { return cache.match(url); }) + .then(function(response) { return response.text(); }) + .then(function(body) { + assert_equals(body, 'some body', + 'Cache.put should accept a string as request.'); + }); + }, 'Cache.put with a string request'); + +cache_test(function(cache) { + return assert_promise_rejects( + cache.put(new Request(test_url), 'Hello world!'), + new TypeError(), + 'Cache.put should only accept a Response object as the response.'); + }, 'Cache.put with an invalid response'); + +cache_test(function(cache) { + return assert_promise_rejects( + cache.put(new Request('file:///etc/passwd'), + new Response(test_body)), + new TypeError(), + 'Cache.put should reject non-HTTP/HTTPS requests with a TypeError.'); + }, 'Cache.put with a non-HTTP/HTTPS request'); + +cache_test(function(cache) { + var response = new Response(test_body); + return cache.put(new Request('relative-url'), response.clone()) + .then(function() { + return cache.match(new URL('relative-url', location.href).href); + }) + .then(function(result) { + assert_object_equals(result, response, + 'Cache.put should accept a relative URL ' + + 'as the request.'); + }); + }, 'Cache.put with a relative URL'); + +cache_test(function(cache) { + var request = new Request('http://example.com/foo', { method: 'HEAD' }); + return assert_promise_rejects( + cache.put(request, new Response(test_body)), + new TypeError(), + 'Cache.put should throw a TypeError for non-GET requests.'); + }, 'Cache.put with a non-GET request'); + +cache_test(function(cache) { + return assert_promise_rejects( + cache.put(new Request(test_url), null), + new TypeError(), + 'Cache.put should throw a TypeError for a null response.'); + }, 'Cache.put with a null response'); + +cache_test(function(cache) { + var request = new Request(test_url, {method: 'POST', body: test_body}); + assert_false(request.bodyUsed, + '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + + 'Request.bodyUsed should be initially false.'); + var copy = new Request(request); + assert_true(request.bodyUsed, + '[https://fetch.spec.whatwg.org/#dom-request] ' + + 'Request constructor should set input\'s used flag.'); + return assert_promise_rejects( + cache.put(request, new Response(test_body)), + new TypeError(), + 'Cache.put should throw a TypeError for a request with used body.'); + }, 'Cache.put with a used request body'); + +cache_test(function(cache) { + var response = new Response(test_body); + assert_false(response.bodyUsed, + '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + + 'Response.bodyUsed should be initially false.'); + return response.text().then(function() { + assert_false( + response.bodyUsed, + '[https://fetch.spec.whatwg.org/#concept-body-consume-body] ' + + 'The text() method should not set "body passed" flag.'); + return cache.put(new Request(test_url), response); + }); + }, 'Cache.put with a used response body'); + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage-keys.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage-keys.js new file mode 100644 index 00000000000..4d7bc623f00 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage-keys.js @@ -0,0 +1,36 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +var test_cache_list = + ['', 'example', 'Another cache name', 'A', 'a', 'ex ample']; + +promise_test(function(test) { + return self.caches.keys() + .then(function(keys) { + assert_true(Array.isArray(keys), + 'CacheStorage.keys should return an Array.'); + return Promise.all(keys.map(function(key) { + return self.caches.delete(key); + })); + }) + .then(function() { + return Promise.all(test_cache_list.map(function(key) { + return self.caches.open(key); + })); + }) + + .then(function() { return self.caches.keys(); }) + .then(function(keys) { + assert_true(Array.isArray(keys), + 'CacheStorage.keys should return an Array.'); + assert_array_equals(keys, + test_cache_list, + 'CacheStorage.keys should only return ' + + 'existing caches.'); + }); + }, 'CacheStorage keys'); + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage-match.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage-match.js new file mode 100644 index 00000000000..06b2888e891 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage-match.js @@ -0,0 +1,123 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +(function() { + var next_index = 1; + + // Returns a transaction (request, response, and url) for a unique URL. + function create_unique_transaction(test) { + var uniquifier = String(next_index++); + var url = 'http://example.com/' + uniquifier; + + return { + request: new Request(url), + response: new Response('hello'), + url: url + }; + } + + self.create_unique_transaction = create_unique_transaction; +})(); + +cache_test(function(cache) { + var transaction = create_unique_transaction(); + + return cache.put(transaction.request.clone(), transaction.response.clone()) + .then(function() { + return self.caches.match(transaction.request); + }) + .then(function(response) { + assert_object_equals(response, transaction.response, + 'The response should not have changed.'); + }); +}, 'CacheStorageMatch with no cache name provided'); + +cache_test(function(cache) { + var transaction = create_unique_transaction(); + + var test_cache_list = ['a', 'b', 'c']; + return cache.put(transaction.request.clone(), transaction.response.clone()) + .then(function() { + return Promise.all(test_cache_list.map(function(key) { + return self.caches.open(key); + })); + }) + .then(function() { + return self.caches.match(transaction.request); + }) + .then(function(response) { + assert_object_equals(response, transaction.response, + 'The response should not have changed.'); + }); +}, 'CacheStorageMatch from one of many caches'); + +promise_test(function(test) { + var transaction = create_unique_transaction(); + + var test_cache_list = ['x', 'y', 'z']; + return Promise.all(test_cache_list.map(function(key) { + return self.caches.open(key); + })) + .then(function() { return caches.open('x'); }) + .then(function(cache) { + return cache.put(transaction.request.clone(), + transaction.response.clone()); + }) + .then(function() { + return self.caches.match(transaction.request, {cacheName: 'x'}); + }) + .then(function(response) { + assert_object_equals(response, transaction.response, + 'The response should not have changed.'); + }) + .then(function() { + return self.caches.match(transaction.request, {cacheName: 'y'}); + }) + .then(function(response) { + assert_equals(response, undefined, + 'Cache y should not have a response for the request.'); + }); +}, 'CacheStorageMatch from one of many caches by name'); + +cache_test(function(cache) { + var transaction = create_unique_transaction(); + return cache.put(transaction.url, transaction.response.clone()) + .then(function() { + return self.caches.match(transaction.request); + }) + .then(function(response) { + assert_object_equals(response, transaction.response, + 'The response should not have changed.'); + }); +}, 'CacheStorageMatch a string request'); + +promise_test(function(test) { + var transaction = create_unique_transaction(); + return self.caches.match(transaction.request) + .then(function(response) { + assert_equals(response, undefined, + 'The response should not be found.'); + }) +}, 'CacheStorageMatch with no cached entry'); + +promise_test(function(test) { + var transaction = create_unique_transaction(); + return self.caches.has('foo') + .then(function(has_foo) { + assert_false(has_foo, "The cache should not exist."); + return self.caches.match(transaction.request, {cacheName: 'foo'}); + }) + .then(function(response) { + assert_equals(response, undefined, + 'The response should not be found.'); + return self.caches.has('foo'); + }) + .then(function(has_foo) { + assert_false(has_foo, "The cache should still not exist."); + }) +}, 'CacheStorageMatch with no caches available but name provided'); + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage.js new file mode 100644 index 00000000000..cb8e0483b22 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-storage.js @@ -0,0 +1,192 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +promise_test(function(t) { + var cache_name = 'cache-storage/foo'; + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function(cache) { + assert_true(cache instanceof Cache, + 'CacheStorage.open should return a Cache.'); + }); + }, 'CacheStorage.open'); + +promise_test(function(t) { + // Note that this test may collide with other tests running in the same + // origin that also uses an empty cache name. + var cache_name = ''; + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function(cache) { + assert_true(cache instanceof Cache, + 'CacheStorage.open should accept an empty name.'); + }); + }, 'CacheStorage.open with an empty name'); + +promise_test(function(t) { + return assert_promise_rejects( + self.caches.open(), + new TypeError(), + 'CacheStorage.open should throw TypeError if called with no arguments.'); + }, 'CacheStorage.open with no arguments'); + +promise_test(function(t) { + var test_cases = [ + { + name: 'cache-storage/lowercase', + should_not_match: + [ + 'cache-storage/Lowercase', + ' cache-storage/lowercase', + 'cache-storage/lowercase ' + ] + }, + { + name: 'cache-storage/has a space', + should_not_match: + [ + 'cache-storage/has' + ] + }, + { + name: 'cache-storage/has\000_in_the_name', + should_not_match: + [ + 'cache-storage/has', + 'cache-storage/has_in_the_name' + ] + } + ]; + return Promise.all(test_cases.map(function(testcase) { + var cache_name = testcase.name; + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function() { + return self.caches.has(cache_name); + }) + .then(function(result) { + assert_true(result, + 'CacheStorage.has should return true for existing ' + + 'cache.'); + }) + .then(function() { + return Promise.all( + testcase.should_not_match.map(function(cache_name) { + return self.caches.has(cache_name) + .then(function(result) { + assert_false(result, + 'CacheStorage.has should only perform ' + + 'exact matches on cache names.'); + }); + })); + }) + .then(function() { + return self.caches.delete(cache_name); + }); + })); + }, 'CacheStorage.has with existing cache'); + +promise_test(function(t) { + return self.caches.has('cheezburger') + .then(function(result) { + assert_false(result, + 'CacheStorage.has should return false for ' + + 'nonexistent cache.'); + }); + }, 'CacheStorage.has with nonexistent cache'); + +promise_test(function(t) { + var cache_name = 'cache-storage/open'; + var cache; + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function(result) { + cache = result; + }) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function(result) { + assert_equals(result, cache, + 'CacheStorage.open should return the named Cache ' + + 'object if it exists.'); + }) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function(result) { + assert_equals(result, cache, + 'CacheStorage.open should return the same ' + + 'instance of an existing Cache object.'); + }); + }, 'CacheStorage.open with existing cache'); + +promise_test(function(t) { + var cache_name = 'cache-storage/delete'; + + return self.caches.delete(cache_name) + .then(function() { + return self.caches.open(cache_name); + }) + .then(function() { return self.caches.delete(cache_name); }) + .then(function(result) { + assert_true(result, + 'CacheStorage.delete should return true after ' + + 'deleting an existing cache.'); + }) + + .then(function() { return self.caches.has(cache_name); }) + .then(function(cache_exists) { + assert_false(cache_exists, + 'CacheStorage.has should return false after ' + + 'fulfillment of CacheStorage.delete promise.'); + }); + }, 'CacheStorage.delete with existing cache'); + +promise_test(function(t) { + return self.caches.delete('cheezburger') + .then(function(result) { + assert_false(result, + 'CacheStorage.delete should return false for a ' + + 'nonexistent cache.'); + }); + }, 'CacheStorage.delete with nonexistent cache'); + +promise_test(function(t) { + var bad_name = 'unpaired\uD800'; + var converted_name = 'unpaired\uFFFD'; // Don't create cache with this name. + return self.caches.has(converted_name) + .then(function(cache_exists) { + assert_false(cache_exists, + 'Test setup failure: cache should not exist'); + }) + .then(function() { return self.caches.open(bad_name); }) + .then(function() { return self.caches.keys(); }) + .then(function(keys) { + assert_true(keys.indexOf(bad_name) !== -1, + 'keys should include cache with bad name'); + }) + .then(function() { return self.caches.has(bad_name); }) + .then(function(cache_exists) { + assert_true(cache_exists, + 'CacheStorage names should be not be converted.'); + }) + .then(function() { return self.caches.has(converted_name); }) + .then(function(cache_exists) { + assert_false(cache_exists, + 'CacheStorage names should be not be converted.'); + }); + }, 'CacheStorage names are DOMStrings not USVStrings'); + +done(); diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-add.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-add.https.html new file mode 100644 index 00000000000..3582b6e06d6 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-add.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Cache.add and Cache.addAll</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-add"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-add.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-delete.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-delete.https.html new file mode 100644 index 00000000000..50bc36d4582 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-delete.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Cache.delete</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-delete"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-delete.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https.html new file mode 100644 index 00000000000..859b1cd0554 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Cache.match and Cache.matchAll</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-match.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-put.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-put.https.html new file mode 100644 index 00000000000..d67f9391a75 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-put.https.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Cache.put</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-put.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html new file mode 100644 index 00000000000..48e9cd383bc --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>CacheStorage.keys</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-storage-keys.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage-match.https.html new file mode 100644 index 00000000000..24c6cea4359 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage-match.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>CacheStorage.match</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage-match"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-storage-match.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage.https.html new file mode 100644 index 00000000000..b199a65a67b --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/serviceworker/cache-storage.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>CacheStorage</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../service-workers/resources/test-helpers.js"></script> +<script> +service_worker_test('../script-tests/cache-storage.js'); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-add.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-add.https.html new file mode 100644 index 00000000000..2cd938356db --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-add.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache Storage: Cache.add and Cache.addAll</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-add"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-add.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-delete.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-delete.https.html new file mode 100644 index 00000000000..3ac04a6b187 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-delete.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache Storage: Cache.delete</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-delete"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-delete.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html new file mode 100644 index 00000000000..093df8db4a8 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Cache Storage: Cache.match and Cache.matchAll</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-match.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-put.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-put.https.html new file mode 100644 index 00000000000..b32cfa2c0bb --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-put.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Cache Storage: Cache.put</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-put.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage-keys.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage-keys.https.html new file mode 100644 index 00000000000..caf1f75f9d0 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage-keys.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache Storage: CacheStorage.keys</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-storage-keys.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage-match.https.html new file mode 100644 index 00000000000..fe8972508f7 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage-match.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache Storage: CacheStorage.match</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage-match"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-storage-match.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage.https.html new file mode 100644 index 00000000000..48cb364bdbf --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-storage.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache Storage: CacheStorage</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script src="../resources/test-helpers.js"></script> +<script src="../script-tests/cache-storage.js"></script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/sandboxed-iframes.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/sandboxed-iframes.https.html new file mode 100644 index 00000000000..aa8613ec77d --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/sandboxed-iframes.https.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<title>Cache Storage: Verify access in sandboxed iframes</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/testharness-helpers.js"></script> +<script> + +function load_iframe(src, sandbox) { + return new Promise(function(resolve, reject) { + var iframe = document.createElement('iframe'); + iframe.onload = function() { resolve(iframe); }; + + iframe.sandbox = sandbox; + iframe.src = src; + + document.documentElement.appendChild(iframe); + }); +} + +function wait_for_message(id) { + return new Promise(function(resolve) { + self.addEventListener('message', function listener(e) { + if (e.data.id === id) { + resolve(e.data); + self.removeEventListener(listener); + } + }); + }); +} + +var counter = 0; + +promise_test(function(t) { + return load_iframe('../resources/iframe.html', + 'allow-scripts allow-same-origin') + .then(function(iframe) { + var id = ++counter; + iframe.contentWindow.postMessage({id: id}, '*'); + return wait_for_message(id); + }) + .then(function(message) { + assert_equals( + message.result, 'allowed', + 'Access should be allowed if sandbox has allow-same-origin'); + }); +}, 'Sandboxed iframe with allow-same-origin is allowed access'); + +promise_test(function(t) { + return load_iframe('../resources/iframe.html', + 'allow-scripts') + .then(function(iframe) { + var id = ++counter; + iframe.contentWindow.postMessage({id: id}, '*'); + return wait_for_message(id); + }) + .then(function(message) { + assert_equals( + message.result, 'denied', + 'Access should be denied if sandbox lacks allow-same-origin'); + assert_equals(message.name, 'SecurityError', + 'Failure should be a SecurityError'); + }); +}, 'Sandboxed iframe without allow-same-origin is denied access'); + +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-add.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-add.https.html new file mode 100644 index 00000000000..b6aa9da8ceb --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-add.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache.add and Cache.addAll</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-add"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-add.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-delete.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-delete.https.html new file mode 100644 index 00000000000..902be7ed3db --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-delete.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Cache.delete</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-delete"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-delete.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-match.https.html new file mode 100644 index 00000000000..b0926fce360 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-match.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Cache.match and Cache.matchAll</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-match"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-match.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-put.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-put.https.html new file mode 100644 index 00000000000..887693061d5 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-put.https.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Cache.put</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-put"> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-put.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage-keys.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage-keys.https.html new file mode 100644 index 00000000000..9f34f5a6ba4 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage-keys.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>CacheStorage.keys</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-storage-keys.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage-match.https.html new file mode 100644 index 00000000000..9d2d47b87db --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage-match.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>CacheStorage.match</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage-match"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-storage-match.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage.https.html new file mode 100644 index 00000000000..4162824b4d7 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/worker/cache-storage.https.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>CacheStorage</title> +<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker('../script-tests/cache-storage.js')); +</script> diff --git a/tests/wpt/web-platform-tests/service-workers/service-workers/resources/test-helpers.js b/tests/wpt/web-platform-tests/service-workers/service-workers/resources/test-helpers.js new file mode 100644 index 00000000000..147ea612c2f --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/service-workers/resources/test-helpers.js @@ -0,0 +1,222 @@ +// Adapter for testharness.js-style tests with Service Workers + +function service_worker_unregister_and_register(test, url, scope) { + if (!scope || scope.length == 0) + return Promise.reject(new Error('tests must define a scope')); + + var options = { scope: scope }; + return service_worker_unregister(test, scope) + .then(function() { + return navigator.serviceWorker.register(url, options); + }) + .catch(unreached_rejection(test, + 'unregister and register should not fail')); +} + +function service_worker_unregister(test, documentUrl) { + return navigator.serviceWorker.getRegistration(documentUrl) + .then(function(registration) { + if (registration) + return registration.unregister(); + }) + .catch(unreached_rejection(test, 'unregister should not fail')); +} + +function service_worker_unregister_and_done(test, scope) { + return service_worker_unregister(test, scope) + .then(test.done.bind(test)); +} + +function unreached_fulfillment(test, prefix) { + return test.step_func(function(result) { + var error_prefix = prefix || 'unexpected fulfillment'; + assert_unreached(error_prefix + ': ' + result); + }); +} + +// Rejection-specific helper that provides more details +function unreached_rejection(test, prefix) { + return test.step_func(function(error) { + var reason = error.message || error.name || error; + var error_prefix = prefix || 'unexpected rejection'; + assert_unreached(error_prefix + ': ' + reason); + }); +} + +// Adds an iframe to the document and returns a promise that resolves to the +// iframe when it finishes loading. The caller is responsible for removing the +// iframe later if needed. +function with_iframe(url) { + return new Promise(function(resolve) { + var frame = document.createElement('iframe'); + frame.src = url; + frame.onload = function() { resolve(frame); }; + document.body.appendChild(frame); + }); +} + +function normalizeURL(url) { + return new URL(url, self.location).toString().replace(/#.*$/, ''); +} + +function wait_for_update(test, registration) { + if (!registration || registration.unregister == undefined) { + return Promise.reject(new Error( + 'wait_for_update must be passed a ServiceWorkerRegistration')); + } + + return new Promise(test.step_func(function(resolve) { + registration.addEventListener('updatefound', test.step_func(function() { + resolve(registration.installing); + })); + })); +} + +function wait_for_state(test, worker, state) { + if (!worker || worker.state == undefined) { + return Promise.reject(new Error( + 'wait_for_state must be passed a ServiceWorker')); + } + if (worker.state === state) + return Promise.resolve(state); + + if (state === 'installing') { + switch (worker.state) { + case 'installed': + case 'activating': + case 'activated': + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + if (state === 'installed') { + switch (worker.state) { + case 'activating': + case 'activated': + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + if (state === 'activating') { + switch (worker.state) { + case 'activated': + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + if (state === 'activated') { + switch (worker.state) { + case 'redundant': + return Promise.reject(new Error( + 'worker is ' + worker.state + ' but waiting for ' + state)); + } + } + + return new Promise(test.step_func(function(resolve) { + worker.addEventListener('statechange', test.step_func(function() { + if (worker.state === state) + resolve(state); + })); + })); +} + +// Declare a test that runs entirely in the ServiceWorkerGlobalScope. The |url| +// is the service worker script URL. This function: +// - Instantiates a new test with the description specified in |description|. +// The test will succeed if the specified service worker can be successfully +// registered and installed. +// - Creates a new ServiceWorker registration with a scope unique to the current +// document URL. Note that this doesn't allow more than one +// service_worker_test() to be run from the same document. +// - Waits for the new worker to begin installing. +// - Imports tests results from tests running inside the ServiceWorker. +function service_worker_test(url, description) { + // If the document URL is https://example.com/document and the script URL is + // https://example.com/script/worker.js, then the scope would be + // https://example.com/script/scope/document. + var scope = new URL('scope' + window.location.pathname, + new URL(url, window.location)).toString(); + promise_test(function(test) { + return service_worker_unregister_and_register(test, url, scope) + .then(function(registration) { + add_completion_callback(function() { + registration.unregister(); + }); + return wait_for_update(test, registration) + .then(function(worker) { + return fetch_tests_from_worker(worker); + }); + }); + }, description); +} + +function get_host_info() { + var ORIGINAL_HOST = '127.0.0.1'; + var REMOTE_HOST = 'localhost'; + var UNAUTHENTICATED_HOST = 'example.test'; + var HTTP_PORT = 8000; + var HTTPS_PORT = 8443; + try { + // In W3C test, we can get the hostname and port number in config.json + // using wptserve's built-in pipe. + // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes + HTTP_PORT = eval('{{ports[http][0]}}'); + HTTPS_PORT = eval('{{ports[https][0]}}'); + ORIGINAL_HOST = eval('\'{{host}}\''); + REMOTE_HOST = 'www1.' + ORIGINAL_HOST; + } catch (e) { + } + return { + HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT, + HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT, + HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT, + HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT, + UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT + }; +} + +function base_path() { + return location.pathname.replace(/\/[^\/]*$/, '/'); +} + +function test_login(test, origin, username, password, cookie) { + return new Promise(function(resolve, reject) { + with_iframe( + origin + + '/serviceworker/resources/fetch-access-control-login.html') + .then(test.step_func(function(frame) { + var channel = new MessageChannel(); + channel.port1.onmessage = test.step_func(function() { + frame.remove(); + resolve(); + }); + frame.contentWindow.postMessage( + {username: username, password: password, cookie: cookie}, + origin, [channel.port2]); + })); + }); +} + +function login(test) { + return test_login(test, 'http://127.0.0.1:8000', + 'username1', 'password1', 'cookie1') + .then(function() { + return test_login(test, 'http://localhost:8000', + 'username2', 'password2', 'cookie2'); + }); +} + +function login_https(test) { + return test_login(test, 'https://127.0.0.1:8443', + 'username1s', 'password1s', 'cookie1') + .then(function() { + return test_login(test, 'https://localhost:8443', + 'username2s', 'password2s', 'cookie2'); + }); +} diff --git a/tests/wpt/web-platform-tests/service-workers/tools/blink-import.py b/tests/wpt/web-platform-tests/service-workers/tools/blink-import.py new file mode 100644 index 00000000000..87ca221c1a3 --- /dev/null +++ b/tests/wpt/web-platform-tests/service-workers/tools/blink-import.py @@ -0,0 +1,204 @@ +import os +import re +import shutil +import glob +import tempfile +import sys +from collections import defaultdict + +here = os.path.abspath(os.path.split(__file__)[0]) + +def get_extra_files(chromium_root): + return [(os.path.join(chromium_root, "LayoutTests", "http", "tests", "resources", "testharness-helpers.js"), + os.path.join("resources", "testharness-helpers.js"))] + +resources_re = re.compile("/?(?:\.\./)*resources/(testharness(?:report)?)\.js") + +def resources_path(line, depth): + return False, resources_re.sub(r"/resources/\1.js", line) + +php_re = re.compile("\.php") + +def python_to_php(line, depth): + return False, php_re.sub(".py", line) + +abs_testharness_helpers_re = re.compile("([\"'])/resources/testharness-helpers.js") +testharness_helpers_re = re.compile("\.\./((?:\.\./)*)resources/testharness-helpers.js") + +def testharness_helpers(line, depth): + if abs_testharness_helpers_re.findall(line): + return False, abs_testharness_helpers_re.sub(r"\1%sresources/testharness-helpers.js" % ("../" * (depth - 1)), line) + return False, testharness_helpers_re.sub(r"\1resources/testharness-helpers.js", line) + +serviceworker_path_re = re.compile("/serviceworker/") +def service_worker_path(line, depth): + return False, serviceworker_path_re.sub("/service-workers/", line) + +localhost_re = re.compile("localhost") +alt_host_re = re.compile("127\.0\.0\.1") +port_http_re = re.compile("8000") +port_https_re = re.compile("8000") + + +def server_names(line, depth): + line, count_0 = localhost_re.subn("{{host}}", line) + line, count_1 = alt_host_re.subn("{{domains[www]}}", line) + line, count_2 = port_http_re.subn("{{ports[http][0]}}", line) + line, count_3 = port_https_re.subn("{{ports[https][0]}}", line) + + count = count_0 + count_1 + count_2 + count_3 + + return bool(count), line + + +def source_paths(chromium_root): + for dirpath, dirnames, filenames in os.walk(chromium_root): + if "chromium" in dirnames: + dirnames.remove("chromium") + for filename in filenames: + if filename.endswith("-expected.txt") or filename.endswith(".php"): + continue + yield os.path.relpath(os.path.join(dirpath, filename), chromium_root) + + +def do_subs(path, line): + depth = len(os.path.split(os.path.sep)) + subs = [resources_path, python_to_php, testharness_helpers, service_worker_path, server_names] + file_is_template = False + for sub in subs: + added_template, line = sub(line, depth) + if added_template: + file_is_template = True + return file_is_template, line + +def get_head(git): + return git("rev-parse", "HEAD") + +def get_changes(git, path, old, new): + data = git("diff", "--name-status", "-z", "--no-renames", "%s..%s" % (old, new), "--", path) + items = data.split("\0") + rv = defaultdict(list) + for status, path in items: + rv[status].append(path) + + return rv + +def copy(src_path, out_dir, rel_path): + dest = os.path.normpath(os.path.join(out_dir, rel_path)) + dest_dir = os.path.split(dest)[0] + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + shutil.copy2(src_path, dest) + +def copy_local_files(local_files, out_root, tmp_dir): + for path in local_files: + rel_path = os.path.relpath(path, out_root) + copy(path, tmp_dir, rel_path) + +def copy_extra_files(chromium_root, tmp_dir): + for in_path, rel_path in get_extra_files(chromium_root): + copy(in_path, tmp_dir, rel_path) + +def sub_changed_filenames(filename_changes, f): + rv = [] + for line in f: + for in_name, out_name in filename_changes.iteritems(): + line = line.replace(in_name, out_name) + rv.append(line) + return "".join(rv) + +testharness_re = re.compile("<script[^>]*src=[\"']?/resources/testharness.js[\"' ][^>]*>") + +def is_top_level_test(path, data): + if os.path.splitext(path)[1] != ".html": + return False + for line in data: + if testharness_re.findall(line): + return True + return False + +def add_suffix(path, suffix): + root, ext = os.path.splitext(path) + return root + ".%s" % suffix + ext + +def main(): + if "--cache-tests" in sys.argv: + sw_path = os.path.join("LayoutTests", "http", "tests", "cachestorage") + out_root = os.path.abspath(os.path.join(here, "..", "cache-storage")) + elif "--sw-tests" in sys.argv: + sw_path = os.path.join("LayoutTests", "http", "tests", "serviceworkers") + out_root = os.path.abspath(os.path.join(here, "..", "service-worker")) + else: + raise ValueError("Must supply either --cache-tests or --sw-tests") + + chromium_root = os.path.abspath(sys.argv[1]) + + work_path = tempfile.mkdtemp() + + test_path = os.path.join(chromium_root, sw_path) + + local_files = glob.glob(os.path.normpath(os.path.join(here, "..", "resources", "*.py"))) + + if not os.path.exists(out_root): + os.mkdir(out_root) + + copy_local_files(local_files, out_root, work_path) + copy_extra_files(chromium_root, work_path) + + path_changes = {} + + for path in source_paths(test_path): + out_path = os.path.join(work_path, path) + out_dir = os.path.dirname(out_path) + if not os.path.exists(out_dir): + os.makedirs(out_dir) + with open(os.path.join(test_path, path)) as in_f: + data = [] + sub = False + for line in in_f: + sub_flag, output_line = do_subs(path, line) + data.append(output_line) + if sub_flag: + sub = True + is_test = is_top_level_test(out_path, data) + + initial_path = out_path + + if is_test: + path_1 = add_suffix(out_path, "https") + else: + path_1 = out_path + + if sub: + path_2 = add_suffix(out_path, "sub") + else: + path_2 = path_1 + + if path_2 != initial_path: + path_changes[initial_path] = path_2 + + with open(path_2, "w") as out_f: + out_f.write("".join(data)) + + filename_changes = {} + + for k, v in path_changes.iteritems(): + if os.path.basename(k) in filename_changes: + print "Got duplicate name:" + os.path.basename(k) + filename_changes[os.path.basename(k)] = os.path.basename(v) + + for path in source_paths(work_path): + full_path = os.path.join(work_path, path) + with open(full_path) as f: + data = sub_changed_filenames(filename_changes, f) + with open(full_path, "w") as f: + f.write(data) + + for dirpath, dirnames, filenames in os.walk(work_path): + for filename in filenames: + in_path = os.path.join(dirpath, filename) + rel_path = os.path.relpath(in_path, work_path) + copy(in_path, out_root, rel_path) + +if __name__ == "__main__": + main() diff --git a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py index 914f7736419..7c0f976a44b 100644 --- a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py +++ b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py @@ -46,6 +46,18 @@ class SourceFile(object): self.meta_flags = self.name.split(".")[1:] + def __getstate__(self): + # Remove computed properties if we pickle this class + rv = self.__dict__.copy() + + if "__cached_properties__" in rv: + cached_properties = rv["__cached_properties__"] + for key in rv.keys(): + if key in cached_properties: + del rv[key] + del rv["__cached_properties__"] + return rv + def name_prefix(self, prefix): """Check if the filename starts with a given prefix diff --git a/tests/wpt/web-platform-tests/tools/manifest/utils.py b/tests/wpt/web-platform-tests/tools/manifest/utils.py index cdd274c9b47..60e00ee74d3 100644 --- a/tests/wpt/web-platform-tests/tools/manifest/utils.py +++ b/tests/wpt/web-platform-tests/tools/manifest/utils.py @@ -40,4 +40,5 @@ class cached_property(object): if self.name not in obj.__dict__: obj.__dict__[self.name] = self.func(obj) + obj.__dict__.setdefault("__cached_properties__", set()).add(self.name) return obj.__dict__[self.name] diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py index 4eeb322cc61..78b982c4970 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py @@ -285,7 +285,7 @@ class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): if response: response.set_error(500, err) response.write() - logger.error(err) + self.logger.error(err) def get_request_line(self): try: diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html index 775c83eff53..d031bfbf3e0 100644 --- a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html +++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html @@ -14,6 +14,8 @@ async_test(function(t) { assert_equals(e.wasClean, false, 'e.wasClean = true'); delete e.wasClean; assert_equals(e.wasClean, false, 'delete e.wasClean'); + delete CloseEvent.prototype.wasClean; + assert_equals(e.wasClean, undefined, 'delete CloseEvent.prototype.wasClean'); t.done(); }); ws.close(); diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html index 8071d220e3a..5ed73191e96 100644 --- a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html +++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html @@ -6,10 +6,11 @@ <div id=log></div> <script> test(function(t) { - delete WebSocket.prototype.readyState; var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/'); ws.close(); delete ws.readyState; - assert_equals(ws.readyState, ws.CLOSING); + assert_equals(ws.readyState, ws.CLOSING, 'delete ws.readyState'); + delete WebSocket.prototype.readyState; + assert_equals(ws.readyState, undefined, 'delete WebSocket.prototype.readyState'); }); </script> diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html index 12118937123..3f0a2a28940 100644 --- a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html +++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html @@ -8,6 +8,8 @@ test(function() { var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/'); delete ws.url; - assert_equals(ws.url, SCHEME_DOMAIN_PORT+'/'); + assert_equals(ws.url, SCHEME_DOMAIN_PORT+'/', 'delete ws.url'); + delete WebSocket.prototype.url; + assert_equals(ws.url, undefined, 'delete WebSocket.prototype.url'); }); </script> diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js index ff0c6fc951c..954c46c07ec 100644 --- a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js +++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js @@ -1,11 +1,13 @@ importScripts("/resources/testharness.js"); -test(function() { +test(function(t) { var i = 0; - addEventListener("message", this.step_func(function listener(evt) { - ++i; - removeEventListener("message", listener, true); - }), true); + addEventListener("message", function listener(evt) { + t.step(function() { + ++i; + removeEventListener("message", listener, true); + }); + }, true); self.dispatchEvent(new Event("message")); self.dispatchEvent(new Event("message")); assert_equals(i, 1); diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html index 79adef16014..4b5af71d516 100644 --- a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html +++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html @@ -21,7 +21,7 @@ async_test(function() { assert_equals(typeof e.message, 'string', 'typeof e.message'); assert_equals(e.filename, document.URL+'#', 'e.filename'); assert_equals(typeof e.lineno, 'number', 'typeof e.lineno'); - assert_equals(typeof e.column, 'number', 'typeof e.column'); + assert_equals(typeof e.colno, 'number', 'typeof e.column'); e.preventDefault(); // "handled" this.done(); }); @@ -29,4 +29,4 @@ async_test(function() { </script> <!-- */ -//-->
\ No newline at end of file +//--> diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html index 96ee06dd207..f6107ada433 100644 --- a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html +++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html @@ -21,7 +21,7 @@ async_test(function() { assert_equals(typeof e.message, 'string', 'typeof e.message'); assert_equals(e.filename, document.URL+'#', 'e.filename'); assert_equals(typeof e.lineno, 'number', 'typeof e.lineno'); - assert_equals(typeof e.column, 'number', 'typeof e.column'); + assert_equals(typeof e.colno, 'number', 'typeof e.column'); e.preventDefault(); // "handled" this.done(); }); @@ -29,4 +29,4 @@ async_test(function() { </script> <!-- */ -//-->
\ No newline at end of file +//--> diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html index 006321675b6..b6a61e2355c 100644 --- a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html +++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html @@ -16,15 +16,11 @@ setup({ }); async_test(function() { var worker = new Worker('#'); - var timeout = setTimeout(this.step_func(function() { - assert_unreached(); - }, 500)); window.onerror = this.step_func(function(a, b, c, d) { - assert_true(typeof a, 'string', 'first argument'); + assert_equals(typeof a, 'string', 'first argument'); assert_equals(b, document.URL+'#', 'second argument'); assert_equals(typeof c, 'number', 'third argument'); assert_equals(typeof d, 'number', 'fourth argument'); - clearTimeout(timeout); this.done(); return true; // "handled" }); |