diff --git a/components/script/dom/html/htmlimageelement.rs b/components/script/dom/html/htmlimageelement.rs
index f5cf6124d9b..d81b098c418 100644
--- a/components/script/dom/html/htmlimageelement.rs
+++ b/components/script/dom/html/htmlimageelement.rs
@@ -6,7 +6,7 @@ use std::cell::Cell;
use std::collections::HashSet;
use std::default::Default;
use std::rc::Rc;
-use std::sync::Arc;
+use std::sync::{Arc, LazyLock};
use std::{char, mem};
use app_units::{AU_PER_PX, Au};
@@ -31,9 +31,10 @@ use num_traits::ToPrimitive;
use pixels::{
CorsStatus, ImageMetadata, PixelFormat, Snapshot, SnapshotAlphaMode, SnapshotPixelFormat,
};
+use regex::Regex;
use servo_url::ServoUrl;
use servo_url::origin::MutableOrigin;
-use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_integer, parse_length};
+use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_length, parse_unsigned_integer};
use style::context::QuirksMode;
use style::parser::ParserContext;
use style::stylesheets::{CssRuleType, Origin};
@@ -1969,6 +1970,21 @@ pub(crate) fn collect_sequence_characters(
(&s[0..i], &s[i..])
}
+///
+/// TODO(#39315): Use the validation rule from Stylo
+fn is_valid_non_negative_integer_string(s: &str) -> bool {
+ s.chars().all(|c| c.is_ascii_digit())
+}
+
+///
+/// TODO(#39315): Use the validation rule from Stylo
+fn is_valid_floating_point_number_string(s: &str) -> bool {
+ static RE: LazyLock =
+ LazyLock::new(|| Regex::new(r"^-?(?:\d+\.\d+|\d+|\.\d+)(?:(e|E)(\+|\-)?\d+)?$").unwrap());
+
+ RE.is_match(s)
+}
+
/// Parse an `srcset` attribute:
/// .
pub fn parse_a_srcset_attribute(input: &str) -> Vec {
@@ -2152,10 +2168,13 @@ pub fn parse_a_srcset_attribute(input: &str) -> Vec {
// > 2. If width and density are not both absent, then let error be yes.
// > 3. Apply the rules for parsing non-negative integers to the descriptor.
// > If the result is 0, let error be yes. Otherwise, let width be the result.
- 'w' if density.is_none() && width.is_none() => {
- match parse_integer(first_part_of_string.chars()) {
+ 'w' if is_valid_non_negative_integer_string(first_part_of_string) &&
+ density.is_none() &&
+ width.is_none() =>
+ {
+ match parse_unsigned_integer(first_part_of_string.chars()) {
Ok(number) if number > 0 => {
- width = Some(number as u32);
+ width = Some(number);
continue;
},
_ => error = true,
@@ -2175,10 +2194,13 @@ pub fn parse_a_srcset_attribute(input: &str) -> Vec {
// what Gecko does, but it also checks to see if the number is a valid HTML-spec compliant
// number first. Not doing that means that we might be parsing numbers that otherwise
// wouldn't parse.
- // TODO: Do what Gecko does and first validate the number passed to the Rust float parser.
- 'x' if width.is_none() && density.is_none() && future_compat_h.is_none() => {
+ 'x' if is_valid_floating_point_number_string(first_part_of_string) &&
+ width.is_none() &&
+ density.is_none() &&
+ future_compat_h.is_none() =>
+ {
match first_part_of_string.parse::() {
- Ok(number) if number.is_normal() && number > 0. => {
+ Ok(number) if number.is_finite() && number >= 0. => {
density = Some(number);
continue;
},
@@ -2194,10 +2216,13 @@ pub fn parse_a_srcset_attribute(input: &str) -> Vec {
// > 2. Apply the rules for parsing non-negative integers to the descriptor.
// > If the result is 0, let error be yes. Otherwise, let future-compat-h be the
// > result.
- 'h' if future_compat_h.is_none() && density.is_none() => {
- match parse_integer(first_part_of_string.chars()) {
+ 'h' if is_valid_non_negative_integer_string(first_part_of_string) &&
+ future_compat_h.is_none() &&
+ density.is_none() =>
+ {
+ match parse_unsigned_integer(first_part_of_string.chars()) {
Ok(number) if number > 0 => {
- future_compat_h = Some(number as u32);
+ future_compat_h = Some(number);
continue;
},
_ => error = true,
diff --git a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html.ini b/tests/wpt/meta/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html.ini
deleted file mode 100644
index cb446a5f799..00000000000
--- a/tests/wpt/meta/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html.ini
+++ /dev/null
@@ -1,156 +0,0 @@
-[parse-a-srcset-attribute.html]
- ["data:,a 1.0w"]
- expected: FAIL
-
- ["data:,a 1e0w"]
- expected: FAIL
-
- ["data:,a 1www"]
- expected: FAIL
-
- ["data:,a +1w"]
- expected: FAIL
-
- ["data:,a 1\\x01w" (trailing U+0001)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+00A0)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+1680)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2000)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2001)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2002)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2003)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2004)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2005)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2006)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2007)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2008)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+2009)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+200A)]
- expected: FAIL
-
- ["data:,a 1w" (trailing U+200C)]
- expected: FAIL
-
- ["data:,a 1w" (trailing U+200D)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+202F)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+205F)]
- expected: FAIL
-
- ["data:,a 1 w" (trailing U+3000)]
- expected: FAIL
-
- ["data:,a 1w" (trailing U+FEFF)]
- expected: FAIL
-
- ["data:,a 0x"]
- expected: FAIL
-
- ["data:,a -0x"]
- expected: FAIL
-
- ["data:,a 1.x"]
- expected: FAIL
-
- ["data:,a +1x"]
- expected: FAIL
-
- ["data:,a 1w 1.0h"]
- expected: FAIL
-
- ["data:,a 1w 1e0h"]
- expected: FAIL
-
- ["data:,a 1w 1hhh"]
- expected: FAIL
-
- ["data:,a 1w +1h"]
- expected: FAIL
-
- ["data:,a 1w 1\\x01h" (trailing U+0001)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+00A0)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+1680)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2000)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2001)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2002)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2003)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2004)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2005)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2006)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2007)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2008)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+2009)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+200A)]
- expected: FAIL
-
- ["data:,a 1w 1h" (trailing U+200C)]
- expected: FAIL
-
- ["data:,a 1w 1h" (trailing U+200D)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+202F)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+205F)]
- expected: FAIL
-
- ["data:,a 1w 1 h" (trailing U+3000)]
- expected: FAIL
-
- ["data:,a 1w 1h" (trailing U+FEFF)]
- expected: FAIL