From 083bb3756fc5ae6b39dd41103792b91c4bdf4d43 Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Thu, 21 Sep 2017 07:07:51 +0000 Subject: [PATCH 1/5] Parse Sizes Attribute --- Cargo.lock | 1 + components/script/dom/htmlimageelement.rs | 76 +++++++++++++ .../dom/webidls/HTMLImageElement.webidl | 2 + components/script/test.rs | 4 + components/style/servo/media_queries.rs | 2 +- tests/unit/script/Cargo.toml | 1 + tests/unit/script/htmlimageelement.rs | 103 ++++++++++++++++++ tests/unit/script/lib.rs | 2 + 8 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 tests/unit/script/htmlimageelement.rs diff --git a/Cargo.lock b/Cargo.lock index 346e0fbcb5ae..0d0e24ef7418 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2676,6 +2676,7 @@ dependencies = [ "msg 0.0.1", "script 0.0.1", "servo_url 0.0.1", + "style 0.0.1", ] [[package]] diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 0410863dc7dd..e16938a1d29c 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use app_units::{Au, AU_PER_PX}; +use cssparser::{Parser, ParserInput}; use document_loader::{LoadType, LoadBlocker}; use dom::activation::Activatable; use dom::attr::Attr; @@ -52,10 +53,17 @@ use script_thread::{Runnable, ScriptThread}; use servo_url::ServoUrl; use servo_url::origin::ImmutableOrigin; use std::cell::{Cell, RefMut}; +use std::char; use std::default::Default; use std::i32; use std::sync::{Arc, Mutex}; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; +use style::context::QuirksMode; +use style::media_queries::MediaQuery; +use style::parser::ParserContext; +use style::values::specified::{Length, ViewportPercentageLength}; +use style::values::specified::length::NoCalcLength; +use style_traits::ParsingMode; use task_source::TaskSource; #[derive(Clone, Copy, HeapSizeOf, JSTraceable)] @@ -66,6 +74,12 @@ enum State { CompletelyAvailable, Broken, } +#[derive(PartialEq)] +#[derive(Debug)] +pub struct Size { + pub query: Option, + pub length: Length, +} #[derive(Clone, Copy, HeapSizeOf, JSTraceable)] enum ImageRequestPhase { Pending, @@ -780,6 +794,63 @@ impl LayoutHTMLImageElementHelpers for LayoutJS { } } +//https://html.spec.whatwg.org/multipage/#parse-a-sizes-attribute +pub fn parse_a_sizes_attribute(input: DOMString, width: Option) -> Vec { + let mut sizes = Vec::::new(); + let unparsed_sizes = input.split(',').collect::>(); + + for unparsed_size in &unparsed_sizes { + let whitespace = unparsed_size.chars().rev().take_while(|c| char::is_whitespace(*c)).count(); + let trimmed: String = unparsed_size.chars().take(unparsed_size.chars().count() - whitespace).collect(); + + if trimmed.is_empty() { + continue; + } + let mut input = ParserInput::new(&trimmed); + let url = ServoUrl::parse("about:blank").unwrap(); + let context = ParserContext::new_for_cssom(&url, + None, + ParsingMode::empty(), + QuirksMode::NoQuirks); + let mut parser = Parser::new(&mut input); + let length = parser.try(|i| Length::parse_non_negative(&context, i)); + println!("\n{:?}", length); + match length { + Ok(len) => sizes.push(Size { + length: len, + query: None + }), + Err(_) => { + let mut media_query_parser = parser; + let media_query = media_query_parser.try(|i| MediaQuery::parse(&context, i)); + if let Ok(query) = media_query { + let length = Length::parse_non_negative(&context, &mut media_query_parser); + if let Ok(length) = length { + sizes.push(Size { + length: length, + query: Some(query) + }) + } + } + }, + } + } + if sizes.is_empty() { + let size = match width { + Some(w) => Size { + length: Length::from_px(w as f32), + query: None + }, + None => Size { + length: Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(100.))), + query: None + }, + }; + sizes.push(size); + } + sizes +} + impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-alt make_getter!(Alt, "alt"); @@ -791,6 +862,11 @@ impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-src make_setter!(SetSrc, "src"); + // https://html.spec.whatwg.org/multipage/#parse-a-sizes-attribute + make_getter!(Sizes, "sizes"); + // https://html.spec.whatwg.org/multipage/#parse-a-sizes-attribute + make_setter!(SetSizes, "sizes"); + // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin fn GetCrossOrigin(&self) -> Option { reflect_cross_origin_attribute(self.upcast::()) diff --git a/components/script/dom/webidls/HTMLImageElement.webidl b/components/script/dom/webidls/HTMLImageElement.webidl index 4f5be4daf7cf..601545cc43e7 100644 --- a/components/script/dom/webidls/HTMLImageElement.webidl +++ b/components/script/dom/webidls/HTMLImageElement.webidl @@ -9,6 +9,8 @@ interface HTMLImageElement : HTMLElement { attribute DOMString alt; [CEReactions] attribute DOMString src; + [CEReactions] + attribute DOMString sizes; // [CEReactions] // attribute DOMString srcset; [CEReactions] diff --git a/components/script/test.rs b/components/script/test.rs index bdd84d681b86..acfead92f2f8 100644 --- a/components/script/test.rs +++ b/components/script/test.rs @@ -15,6 +15,10 @@ pub mod area { pub use dom::htmlareaelement::{Area, Shape}; } +pub mod sizes { + pub use dom::htmlimageelement::{parse_a_sizes_attribute, Size}; +} + pub mod size_of { use dom::characterdata::CharacterData; use dom::element::Element; diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index f3a8670adcf1..5dd6615fd641 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -164,7 +164,7 @@ pub enum ExpressionKind { /// http://dev.w3.org/csswg/mediaqueries-3/#media1 #[derive(Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub struct Expression(ExpressionKind); +pub struct Expression(pub ExpressionKind); impl Expression { /// The kind of expression we're, just for unit testing. diff --git a/tests/unit/script/Cargo.toml b/tests/unit/script/Cargo.toml index d88f4d9a75f6..7785cced6a9c 100644 --- a/tests/unit/script/Cargo.toml +++ b/tests/unit/script/Cargo.toml @@ -14,3 +14,4 @@ euclid = "0.15" msg = {path = "../../../components/msg"} script = {path = "../../../components/script"} servo_url = {path = "../../../components/url"} +style = {path = "../../../components/style"} diff --git a/tests/unit/script/htmlimageelement.rs b/tests/unit/script/htmlimageelement.rs new file mode 100644 index 000000000000..4405bb0d6f52 --- /dev/null +++ b/tests/unit/script/htmlimageelement.rs @@ -0,0 +1,103 @@ +/* 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::test::DOMString; +use script::test::sizes::{parse_a_sizes_attribute, Size}; +use style::media_queries::{MediaQuery, MediaQueryType}; +use style::media_queries::Expression; +use style::servo::media_queries::{ExpressionKind, Range}; +use style::values::specified::{Length, NoCalcLength, AbsoluteLength, ViewportPercentageLength}; + + +pub fn test_length_for_no_default_provided(len: f32) -> Length { + let length = Length::NoCalc(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(len))); + return length; +} + +#[test] +fn no_default_provided() { + let mut a = vec![]; + let length = test_length_for_no_default_provided(100f32); + let size = Size { query: None, length: length }; + a.push(size); + assert_eq!(parse_a_sizes_attribute(DOMString::new(), None), a); + println!("{:?}", parse_a_sizes_attribute(DOMString::new(), None)); +} + +pub fn test_length_for_default_provided(len: f32) -> Length { + let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len))); + return length; +} + +#[test] +fn default_provided() { + let mut a = vec![]; + let length = test_length_for_default_provided(2f32); + let size = Size { query: None, length: length }; + a.push(size); + assert_eq!(parse_a_sizes_attribute(DOMString::new(), Some(2)), a); + println!("{:?}", parse_a_sizes_attribute(DOMString::new(), Some(2))); +} + +pub fn test_media_query(len: f32) -> MediaQuery { + let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len))); + let expr = Expression(ExpressionKind::Width(Range::Max(length))); + let media_query = MediaQuery { + qualifier: None, + media_type: MediaQueryType::All, + expressions: vec![expr] + }; + media_query +} + +pub fn test_length(len: f32) -> Length { + let length = Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(len))); + return length; +} + +#[test] +fn one_value() { + let mut a = vec![]; + let media_query = test_media_query(200f32); + let length = test_length(545f32); + let size = Size { query: Some(media_query), length: length }; + a.push(size); + assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 200px) 545px"), None), a); +} + +#[test] +fn more_then_one_value() { + let media_query = test_media_query(900f32); + let length = test_length(1000f32); + let size = Size { query: Some(media_query), length: length }; + let media_query1 = test_media_query(900f32); + let length1 = test_length(50f32); + let size1 = Size { query: Some(media_query1), length: length1 }; + let a = &[size, size1]; + assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"), + None), a); +} + +#[test] +fn no_extra_whitespace() { + let mut a = vec![]; + let media_query = test_media_query(200f32); + let length = test_length(545f32); + let size = Size { query: Some(media_query), length: length }; + a.push(size); + assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 200px) 545px"), None), a); +} + +#[test] +fn extra_whitespace() { + let media_query = test_media_query(900f32); + let length = test_length(1000f32); + let size = Size { query: Some(media_query), length: length }; + let media_query1 = test_media_query(900f32); + let length1 = test_length(50f32); + let size1 = Size { query: Some(media_query1), length: length1 }; + let a = &[size, size1]; +assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"), + None), a); +} \ No newline at end of file diff --git a/tests/unit/script/lib.rs b/tests/unit/script/lib.rs index 83131e51dd23..21b89a304c56 100644 --- a/tests/unit/script/lib.rs +++ b/tests/unit/script/lib.rs @@ -6,10 +6,12 @@ extern crate euclid; extern crate msg; extern crate script; extern crate servo_url; +extern crate style; #[cfg(test)] mod origin; #[cfg(all(test, target_pointer_width = "64"))] mod size_of; #[cfg(test)] mod textinput; #[cfg(test)] mod headers; #[cfg(test)] mod htmlareaelement; +#[cfg(test)] mod htmlimageelement; From f4321b52f91facf45858af410e51823de213ebe3 Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Thu, 21 Sep 2017 12:15:32 +0000 Subject: [PATCH 2/5] Parse Sizes Attribute --- components/script/dom/htmlimageelement.rs | 2 -- tests/unit/script/htmlimageelement.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index e16938a1d29c..652b44972308 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -798,7 +798,6 @@ impl LayoutHTMLImageElementHelpers for LayoutJS { pub fn parse_a_sizes_attribute(input: DOMString, width: Option) -> Vec { let mut sizes = Vec::::new(); let unparsed_sizes = input.split(',').collect::>(); - for unparsed_size in &unparsed_sizes { let whitespace = unparsed_size.chars().rev().take_while(|c| char::is_whitespace(*c)).count(); let trimmed: String = unparsed_size.chars().take(unparsed_size.chars().count() - whitespace).collect(); @@ -814,7 +813,6 @@ pub fn parse_a_sizes_attribute(input: DOMString, width: Option) -> Vec sizes.push(Size { length: len, diff --git a/tests/unit/script/htmlimageelement.rs b/tests/unit/script/htmlimageelement.rs index 4405bb0d6f52..58e566dbda18 100644 --- a/tests/unit/script/htmlimageelement.rs +++ b/tests/unit/script/htmlimageelement.rs @@ -100,4 +100,4 @@ fn extra_whitespace() { let a = &[size, size1]; assert_eq!(parse_a_sizes_attribute(DOMString::from("(max-width: 900px) 1000px, (max-width: 900px) 50px"), None), a); -} \ No newline at end of file +} From ce14eab6f4ebced766c9d4b6e274982503eabac9 Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Mon, 25 Sep 2017 18:37:34 +0000 Subject: [PATCH 3/5] Parse sizes attribute- Updates --- components/script/dom/htmlimageelement.rs | 3 ++- tests/unit/script/htmlimageelement.rs | 10 ++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 652b44972308..d23d17a6bf58 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -74,6 +74,7 @@ enum State { CompletelyAvailable, Broken, } + #[derive(PartialEq)] #[derive(Debug)] pub struct Size { @@ -822,7 +823,7 @@ pub fn parse_a_sizes_attribute(input: DOMString, width: Option) -> Vec Length { #[test] fn no_default_provided() { - let mut a = vec![]; + let a = vec![size]; let length = test_length_for_no_default_provided(100f32); let size = Size { query: None, length: length }; a.push(size); assert_eq!(parse_a_sizes_attribute(DOMString::new(), None), a); - println!("{:?}", parse_a_sizes_attribute(DOMString::new(), None)); } pub fn test_length_for_default_provided(len: f32) -> Length { @@ -32,12 +31,11 @@ pub fn test_length_for_default_provided(len: f32) -> Length { #[test] fn default_provided() { - let mut a = vec![]; + let a = vec![size]; let length = test_length_for_default_provided(2f32); let size = Size { query: None, length: length }; a.push(size); assert_eq!(parse_a_sizes_attribute(DOMString::new(), Some(2)), a); - println!("{:?}", parse_a_sizes_attribute(DOMString::new(), Some(2))); } pub fn test_media_query(len: f32) -> MediaQuery { @@ -58,7 +56,7 @@ pub fn test_length(len: f32) -> Length { #[test] fn one_value() { - let mut a = vec![]; + let a = vec![size]; let media_query = test_media_query(200f32); let length = test_length(545f32); let size = Size { query: Some(media_query), length: length }; @@ -81,7 +79,7 @@ fn more_then_one_value() { #[test] fn no_extra_whitespace() { - let mut a = vec![]; + let a = vec![size]; let media_query = test_media_query(200f32); let length = test_length(545f32); let size = Size { query: Some(media_query), length: length }; From 05185e2b65a3f1ccf1d245bbd67295fd5baebfc9 Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Mon, 25 Sep 2017 18:49:51 +0000 Subject: [PATCH 4/5] Parse Sizes attribute --- components/script/dom/htmlimageelement.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index d23d17a6bf58..1082284d2c9a 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -798,8 +798,7 @@ impl LayoutHTMLImageElementHelpers for LayoutJS { //https://html.spec.whatwg.org/multipage/#parse-a-sizes-attribute pub fn parse_a_sizes_attribute(input: DOMString, width: Option) -> Vec { let mut sizes = Vec::::new(); - let unparsed_sizes = input.split(',').collect::>(); - for unparsed_size in &unparsed_sizes { + for unparsed_size in input.split(',') { let whitespace = unparsed_size.chars().rev().take_while(|c| char::is_whitespace(*c)).count(); let trimmed: String = unparsed_size.chars().take(unparsed_size.chars().count() - whitespace).collect(); From 2f31ff0c638ada3acde9e90f25c61f809b2681c5 Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Mon, 25 Sep 2017 19:44:15 +0000 Subject: [PATCH 5/5] Parse Sizes attribute --- tests/unit/script/htmlimageelement.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/script/htmlimageelement.rs b/tests/unit/script/htmlimageelement.rs index b694158432e8..df5a745b5b6e 100644 --- a/tests/unit/script/htmlimageelement.rs +++ b/tests/unit/script/htmlimageelement.rs @@ -17,7 +17,7 @@ pub fn test_length_for_no_default_provided(len: f32) -> Length { #[test] fn no_default_provided() { - let a = vec![size]; + let mut a = vec![]; let length = test_length_for_no_default_provided(100f32); let size = Size { query: None, length: length }; a.push(size); @@ -31,7 +31,7 @@ pub fn test_length_for_default_provided(len: f32) -> Length { #[test] fn default_provided() { - let a = vec![size]; + let mut a = vec![]; let length = test_length_for_default_provided(2f32); let size = Size { query: None, length: length }; a.push(size); @@ -56,7 +56,7 @@ pub fn test_length(len: f32) -> Length { #[test] fn one_value() { - let a = vec![size]; + let mut a = vec![]; let media_query = test_media_query(200f32); let length = test_length(545f32); let size = Size { query: Some(media_query), length: length }; @@ -79,7 +79,7 @@ fn more_then_one_value() { #[test] fn no_extra_whitespace() { - let a = vec![size]; + let mut a = vec![]; let media_query = test_media_query(200f32); let length = test_length(545f32); let size = Size { query: Some(media_query), length: length };