Bug 2028949: Upgrade cssparser to 0.37.0 (r=emilio,supply-chain-reviewers,firefox-style-system-reviewers)

Signed-off-by: Nico Burns <nico@nicoburns.com>

Differential Revision: https://phabricator.services.mozilla.com/D291829
This commit is contained in:
Nico Burns
2026-04-02 19:37:57 +00:00
committed by ealvarez@mozilla.com
parent f6632a42b1
commit f993b0a200
29 changed files with 305 additions and 157 deletions
Generated
+4 -4
View File
@@ -1434,9 +1434,9 @@ dependencies = [
[[package]]
name = "cssparser"
version = "0.36.0"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2"
checksum = "8c9cdaae01d5ed7882b04d795e7f752f46ff52d2fa3b50a20d28c464510bba98"
dependencies = [
"cssparser-macros",
"dtoa-short",
@@ -1447,9 +1447,9 @@ dependencies = [
[[package]]
name = "cssparser-macros"
version = "0.6.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
checksum = "10a2a99df6e410a8ff4245aa2006499ea662245f967cc7c0a38c83ef8eb44dbf"
dependencies = [
"quote",
"syn",
+1 -1
View File
@@ -16,7 +16,7 @@ servo = ["string_cache"]
[dependencies]
app_units = "0.7"
cssparser = "0.36"
cssparser = "0.37"
euclid = "0.22"
selectors = { path = "../selectors" }
servo_arc = { path = "../servo_arc" }
+1 -1
View File
@@ -21,7 +21,7 @@ to_shmem = ["dep:to_shmem", "dep:to_shmem_derive"]
[dependencies]
bitflags = "2"
cssparser = "0.36"
cssparser = "0.37"
derive_more = { version = "2", features = ["add", "add_assign"] }
rustc-hash = "2.1.1"
log = "0.4"
+1 -1
View File
@@ -55,7 +55,7 @@ arrayvec = "0.7"
atomic_refcell = "0.1"
bitflags = "2"
byteorder = "1.0"
cssparser = "0.36"
cssparser = "0.37"
derive_more = { version = "2", features = ["add", "add_assign", "deref", "deref_mut", "from"] }
dom = { path = "../../../dom/base/rust" }
new_debug_unreachable = "1.0"
+1 -1
View File
@@ -18,7 +18,7 @@ gecko = ["nsstring"]
[dependencies]
app_units = "0.7"
bitflags = "2"
cssparser = "0.36"
cssparser = "0.37"
euclid = "0.22"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = { path = "../../../xpcom/rust/malloc_size_of_derive" }
+1 -1
View File
@@ -23,7 +23,7 @@ string_cache = ["dep:string_cache"]
thin-vec = ["dep:thin-vec"]
[dependencies]
cssparser = { version = "0.36", optional = true }
cssparser = { version = "0.37", optional = true }
servo_arc = { version = "0.4.0", path = "../servo_arc", optional = true }
smallbitvec = { version = "2.3.0", optional = true }
smallvec = { version = "1.13", optional = true }
+1 -1
View File
@@ -15,7 +15,7 @@ gecko_refcount_logging = ["style/gecko_refcount_logging", "servo_arc/gecko_refco
[dependencies]
atomic_refcell = "0.1"
cssparser = "0.36"
cssparser = "0.37"
cstr = "0.2"
dom = { path = "../../../dom/base/rust" }
ipdl_utils = { path = "../../../ipc/rust/ipdl_utils" }
+1 -1
View File
@@ -12,7 +12,7 @@ doctest = false
[dependencies]
byteorder = "1.0"
app_units = "0.7"
cssparser = "0.36"
cssparser = "0.37"
euclid = "0.22"
html5ever = "0.22"
parking_lot = "0.10"
+12
View File
@@ -1759,6 +1759,12 @@ who = "Diego Escalante <descalante@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.35.0 -> 0.36.0"
[[audits.cssparser]]
who = "Nico Burns <nico@nicoburns.com>"
criteria = "safe-to-deploy"
delta = "0.36.0 -> 0.37.0"
notes = "First-party code"
[[audits.cssparser-color]]
who = "Emilio Cobos Álvarez <emilio@crisal.io>"
criteria = "safe-to-deploy"
@@ -1785,6 +1791,12 @@ criteria = "safe-to-deploy"
delta = "0.6.1 -> 0.6.1@git:aaa966d9d6ae70c4b8a62bb5e3a14c068bb7dff0"
notes = "No changes from already-certified upstream, but needed because it lives in the same git repo as the cssparser crate."
[[audits.cssparser-macros]]
who = "Nico Burns <nico@nicoburns.com>"
criteria = "safe-to-deploy"
delta = "0.6.1 -> 0.7.0"
notes = "First party code"
[[audits.cstr]]
who = "Emilio Cobos Álvarez <emilio@crisal.io>"
criteria = "safe-to-deploy"
+1 -1
View File
@@ -1 +1 @@
{"files":{".cargo_vcs_info.json":"705364eb932e3234e7257532d9c3a92812353a3c7352932bc881334763c23ff0","Cargo.toml":"d4a43ad31d5048cf19ee80ec38de90fa98b9b9902b97d61e4edc940246806295","Cargo.toml.orig":"3edb5c90ee723720d1dce0e64ce931bd84244ccf9f3a0be9fc600dde7bc0ef50","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","lib.rs":"10e68d5a92a053ff498cb1caa8290e508f691e32b73222a5a4737ee9a4097ce2"},"package":"13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"}
{"files":{".cargo_vcs_info.json":"fdbe37376e47a3c284309f86ab0b5989e42e4463e3ecede7189baf46e2160a0c","Cargo.lock":"5ff924474f6c0b10bb1d92311ec0cb784eaecb036d5a7ff3362d6efe9ccb669e","Cargo.toml":"40668dc2f688436f818ce0e8739b3b4c517afc242e5ce9145db706d1960fbd7e","Cargo.toml.orig":"41dd3893b2f05015715e6205a4c60f31592790dd6615b7e74aabbb846eb6ca93","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","lib.rs":"ba8fe37213029ab22423da328c53171ce9807882ab9d898bd909383dd9d3803f"},"package":"10a2a99df6e410a8ff4245aa2006499ea662245f967cc7c0a38c83ef8eb44dbf"}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"git": {
"sha1": "0ebd17bcd13808f087b083f34d2f816e380b5155"
"sha1": "4c49486494fb24dc01390e3baca9698ef1744c71"
},
"path_in_vcs": "macros"
}
+46
View File
@@ -0,0 +1,46 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cssparser-macros"
version = "0.7.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
+10 -2
View File
@@ -12,19 +12,27 @@
[package]
edition = "2018"
name = "cssparser-macros"
version = "0.6.1"
version = "0.7.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Procedural macros for cssparser"
documentation = "https://docs.rs/cssparser-macros/"
readme = false
license = "MPL-2.0"
repository = "https://github.com/servo/rust-cssparser"
[lib]
name = "cssparser_macros"
path = "lib.rs"
proc-macro = true
[dependencies.quote]
version = "1"
version = "1.0.29"
[dependencies.syn]
version = "2"
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "cssparser-macros"
version = "0.6.1"
version = "0.7.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
description = "Procedural macros for cssparser"
documentation = "https://docs.rs/cssparser-macros/"
@@ -13,5 +13,5 @@ path = "lib.rs"
proc-macro = true
[dependencies]
quote = "1"
quote = "1.0.29"
syn = {version = "2", features = ["full", "extra-traits"]}
+12 -44
View File
@@ -6,38 +6,6 @@ extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn _cssparser_internal_max_len(input: TokenStream) -> TokenStream {
struct Input {
max_length: usize,
}
impl syn::parse::Parse for Input {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
let mut max_length = 0;
while !input.is_empty() {
if input.peek(syn::Token![_]) {
input.parse::<syn::Token![_]>().unwrap();
continue;
}
let lit: syn::LitStr = input.parse()?;
let value = lit.value();
if value.to_ascii_lowercase() != value {
return Err(syn::Error::new(lit.span(), "must be ASCII-lowercase"));
}
max_length = max_length.max(value.len());
}
Ok(Input { max_length })
}
}
let Input { max_length } = syn::parse_macro_input!(input);
quote::quote!(
pub(super) const MAX_LENGTH: usize = #max_length;
)
.into()
}
fn get_byte_from_lit(lit: &syn::Lit) -> u8 {
if let syn::Lit::Byte(ref byte) = *lit {
byte.value()
@@ -48,9 +16,7 @@ fn get_byte_from_lit(lit: &syn::Lit) -> u8 {
fn get_byte_from_expr_lit(expr: &syn::Expr) -> u8 {
match *expr {
syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => {
get_byte_from_lit(lit)
}
syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => get_byte_from_lit(lit),
_ => unreachable!(),
}
}
@@ -63,15 +29,17 @@ fn parse_pat_to_table<'a>(
table: &mut [u8; 256],
) {
match pat {
&syn::Pat::Lit(syn::PatLit { ref lit, .. }) => {
syn::Pat::Lit(syn::PatLit { ref lit, .. }) => {
let value = get_byte_from_lit(lit);
if table[value as usize] == 0 {
table[value as usize] = case_id;
}
}
&syn::Pat::Range(syn::PatRange { ref start, ref end, .. }) => {
let lo = get_byte_from_expr_lit(&start.as_ref().unwrap());
let hi = get_byte_from_expr_lit(&end.as_ref().unwrap());
syn::Pat::Range(syn::PatRange {
ref start, ref end, ..
}) => {
let lo = get_byte_from_expr_lit(start.as_ref().unwrap());
let hi = get_byte_from_expr_lit(end.as_ref().unwrap());
for value in lo..hi {
if table[value as usize] == 0 {
table[value as usize] = case_id;
@@ -81,14 +49,14 @@ fn parse_pat_to_table<'a>(
table[hi as usize] = case_id;
}
}
&syn::Pat::Wild(_) => {
syn::Pat::Wild(_) => {
for byte in table.iter_mut() {
if *byte == 0 {
*byte = case_id;
}
}
}
&syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
assert_eq!(*wildcard, None);
*wildcard = Some(ident);
for byte in table.iter_mut() {
@@ -97,7 +65,7 @@ fn parse_pat_to_table<'a>(
}
}
}
&syn::Pat::Or(syn::PatOr { ref cases, .. }) => {
syn::Pat::Or(syn::PatOr { ref cases, .. }) => {
for case in cases {
parse_pat_to_table(case, case_id, wildcard, table);
}
@@ -162,7 +130,7 @@ pub fn match_byte(input: TokenStream) -> TokenStream {
for (i, ref arm) in arms.iter().enumerate() {
let case_id = i + 1;
let index = case_id as isize;
let name = syn::Ident::new(&format!("Case{}", case_id), arm.span());
let name = syn::Ident::new(&format!("Case{case_id}"), arm.span());
let pat = &arm.pat;
parse_pat_to_table(pat, case_id as u8, &mut wildcard, &mut table);
@@ -177,7 +145,7 @@ pub fn match_byte(input: TokenStream) -> TokenStream {
let mut table_content = Vec::new();
for entry in table.iter() {
let name: syn::Path = syn::parse_str(&format!("Case::Case{}", entry)).unwrap();
let name: syn::Path = syn::parse_str(&format!("Case::Case{entry}")).unwrap();
table_content.push(name);
}
let table = quote::quote!(static __CASES: [Case; 256] = [#(#table_content),*];);
+1 -1
View File
@@ -1 +1 @@
{"files":{".cargo_vcs_info.json":"f0af6c4fb3969fea2c76a982abcec85912c5459244202577dc50daa63652305d",".github/workflows/main.yml":"1cdb64fe881ec0d0e3fa3c400135af3bf22f33a3e91a71b5176389b86b815412","Cargo.lock":"e2f8b97f2e23945fdda945aed3d038046fe1e994106bce07b429c42a60fe8b1b","Cargo.toml":"1a1bf623e831c9015a9c91aac6f960825e2d397be3974fcce56ebf73dd9d7aec","Cargo.toml.orig":"5ac4e40a687563e07fd9e8988d4ba064ce1453c59c635648e94d3b25b1ba22b5","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"95e81e8f22062ba196eb8229a749327c063620ccf31ce1dd01b7ea0529840280","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"e0f43f7fd0e4ef2051e55675ae9ca30215382b403472f3d0ebe84f55899e857d","src/cow_rc_str.rs":"88edf6a4a1b3d4338885a8eacc29a9e7115d4fae0f227c9a81a4d53c5a546693","src/from_bytes.rs":"1223c1ccf619735ccf7c28a8d154d516aa117fdbddcf091e2e8952e68fe53a80","src/lib.rs":"817a739180a561f9e7e45c539b4191af1286ca61e29cb2b8a366cd21bd5c7a9e","src/macros.rs":"64ad9e506e5cea52767a5177779ac4a1cbdac1b2188abaa1291e9feb8f1653bf","src/nth.rs":"972cc94275126e747c95621e8c5f56ce5d869924e60bb0dc990f4c98f3d74890","src/parser.rs":"88dd21884a5f46edcd5687a6f64e5ca83f41562bf536f40704d26455f46b3bcd","src/rules_and_declarations.rs":"b9e2a9b8b6c52b0fc18237f71432ed37276ba274f1c8257570c704bfc05579a3","src/serializer.rs":"e3aa3e0ca294d34b3850e54680f4475143aa09fcb85129fa85d7084c4c9ea09e","src/size_of_tests.rs":"f29de7c5cb681cb36b81d22f6b103df61e3bf1406758fa5606138dbf6b49db58","src/tests.rs":"e7b0658dfdc13717c55dc2d0305ad3e237c3d9df489619bb69685652b9f7d482","src/tokenizer.rs":"952c763521e34572590c30539b9673f55cf567ac44cf8fb54dbfb864800f7e1a","src/unicode_range.rs":"7ea876f64e2c83679e9cecccf9f332bebffe512f487da47a0c06e423c8662110"},"package":"dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2"}
{"files":{".cargo_vcs_info.json":"f962147af040486a7d5e1159d3724d7e2bd4050cf0265f1e0087a263e2a915e0",".github/workflows/main.yml":"a434e6e61ff47b5b4a9460a7a5fb8726ed514bedb2f095ecf4a9bea335518e10","Cargo.lock":"5513b6d4307ff5b4ea29818a0ac623d8af8f1e9b8240849c45c681b29c3d41dc","Cargo.toml":"0ac783c96e15668a9efd9e43c9218953c49bf1441779ea622d065d7b643c7697","Cargo.toml.orig":"1b018bdc84c21092d9dfc56f33b722ee0cea01547d59821dd5eec2f3338b90e6","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"95e81e8f22062ba196eb8229a749327c063620ccf31ce1dd01b7ea0529840280","docs/.nojekyll":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"5d6e933cea7b1eaca4f257a682f8c3597f185e21bc64c53cf77f0c91e6ea9b84","src/cow_rc_str.rs":"88edf6a4a1b3d4338885a8eacc29a9e7115d4fae0f227c9a81a4d53c5a546693","src/from_bytes.rs":"1223c1ccf619735ccf7c28a8d154d516aa117fdbddcf091e2e8952e68fe53a80","src/lib.rs":"0ed4b253cac886f3b365958279c5efa094f7b4bfd4e44896b6ebaf32994d6fa9","src/macros.rs":"731f263f6a7a1dd41029e522b58f2c8e193ddd3243f814da588635283128cd36","src/nth.rs":"86b0a3c19ecaac27ca95a97ee0f9f703b0d21f7b14c3e6d2f2ce12af78cb24a2","src/parser.rs":"c6d56e8921b4cb2f02d7b9620044f0d79fc911350d73199c7797ad690b4cc79f","src/rules_and_declarations.rs":"b9e2a9b8b6c52b0fc18237f71432ed37276ba274f1c8257570c704bfc05579a3","src/serializer.rs":"ccc3f0e44189284b46dfad1d48ca5c21860f2c7e1c00540da5cee77e0c891275","src/size_of_tests.rs":"f29de7c5cb681cb36b81d22f6b103df61e3bf1406758fa5606138dbf6b49db58","src/tests.rs":"5ed73aa37e42ebb06bccd0860686504d3467ae3ddd75e513812dfaf5a83e926a","src/tokenizer.rs":"0be69dc2fb909133a4e3148e1f70b5fae4328175ad49634b465f4126f5351ebd","src/unicode_range.rs":"7ea876f64e2c83679e9cecccf9f332bebffe512f487da47a0c06e423c8662110"},"package":"8c9cdaae01d5ed7882b04d795e7f752f46ff52d2fa3b50a20d28c464510bba98"}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"git": {
"sha1": "9339ddd71443463dfb85d1185ad50cd98b34bc8f"
"sha1": "4c49486494fb24dc01390e3baca9698ef1744c71"
},
"path_in_vcs": ""
}
+9 -14
View File
@@ -18,16 +18,14 @@ jobs:
- nightly
- beta
- stable
- 1.68.0
- 1.71.0
features:
-
- --features dummy_match_byte
- --no-default-features
- --features malloc_size_of
include:
- toolchain: nightly
features: --features bench
- toolchain: nightly
features: --features bench,dummy_match_byte
steps:
- uses: actions/checkout@v2
@@ -43,29 +41,26 @@ jobs:
run: cargo fmt --check && cargo clippy -- -Dwarnings
- name: Cargo build
run: cargo build ${{ matrix.features }}
run: cargo build -p cssparser ${{ matrix.features }}
- name: Cargo doc
run: cargo doc ${{ matrix.features }}
run: cargo doc -p cssparser ${{ matrix.features }}
- name: Cargo test
run: cargo test ${{ matrix.features }}
run: cargo test -p cssparser ${{ matrix.features }}
- name: macros build
run: cargo build
working-directory: macros
run: cargo build -p cssparser-macros
- name: Color build
run: cargo build
working-directory: color
run: cargo build -p cssparser-color
- name: Color test
run: cargo test
working-directory: color
run: cargo test -p cssparser-color
- name: Cargo miri test
if: "matrix.toolchain == 'nightly'"
run: cargo miri test --features skip_long_tests ${{ matrix.features }}
run: cargo miri test -p cssparser --features skip_long_tests ${{ matrix.features }}
build_result:
name: Result
+3 -3
View File
@@ -10,7 +10,7 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cssparser"
version = "0.36.0"
version = "0.37.0"
dependencies = [
"cssparser-macros",
"difference",
@@ -26,9 +26,9 @@ dependencies = [
[[package]]
name = "cssparser-macros"
version = "0.6.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
checksum = "10a2a99df6e410a8ff4245aa2006499ea662245f967cc7c0a38c83ef8eb44dbf"
dependencies = [
"quote",
"syn",
+11 -4
View File
@@ -11,9 +11,9 @@
[package]
edition = "2018"
rust-version = "1.68"
rust-version = "1.71"
name = "cssparser"
version = "0.36.0"
version = "0.37.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
build = false
exclude = [
@@ -38,7 +38,12 @@ repository = "https://github.com/servo/rust-cssparser"
[features]
bench = []
dummy_match_byte = []
default = [
"fast_match_byte",
"fast_match_color",
]
fast_match_byte = ["dep:cssparser-macros"]
fast_match_color = ["dep:phf"]
skip_long_tests = []
[lib]
@@ -46,7 +51,8 @@ name = "cssparser"
path = "src/lib.rs"
[dependencies.cssparser-macros]
version = "0.6.1"
version = "0.7.0"
optional = true
[dependencies.dtoa-short]
version = "0.3"
@@ -62,6 +68,7 @@ default-features = false
[dependencies.phf]
version = "0.13.1"
features = ["macros"]
optional = true
[dependencies.serde]
version = "1.0"
+17 -12
View File
@@ -1,6 +1,6 @@
[package]
name = "cssparser"
version = "0.36.0"
version = "0.37.0"
authors = ["Simon Sapin <simon.sapin@exyr.org>"]
description = "Rust implementation of CSS Syntax Level 3"
@@ -10,33 +10,38 @@ readme = "README.md"
keywords = ["css", "syntax", "parser"]
license = "MPL-2.0"
edition = "2018"
rust-version = "1.68"
rust-version = "1.71"
exclude = ["src/css-parsing-tests/**", "src/big-data-url.css"]
[dependencies]
dtoa-short = "0.3"
itoa = "1.0"
smallvec = "1.0"
# Optional dependencies
cssparser-macros = { path = "./macros", version = "0.7.0", optional = true }
malloc_size_of = { version = "0.1", default-features = false, optional = true }
phf = { version = "0.13.1", features = ["macros"], optional = true }
serde = { version = "1.0", features = ["derive"], optional = true }
[dev-dependencies]
serde_json = "1.0.25"
difference = "2.0"
encoding_rs = "0.8"
[dependencies]
cssparser-macros = { path = "./macros", version = "0.6.1" }
dtoa-short = "0.3"
itoa = "1.0"
phf = { version = "0.13.1", features = ["macros"] }
serde = { version = "1.0", features = ["derive"], optional = true }
malloc_size_of = { version = "0.1", default-features = false, optional = true }
smallvec = "1.0"
[profile.profiling]
inherits = "release"
debug = true
[features]
default = ["fast_match_byte", "fast_match_color"]
bench = []
dummy_match_byte = []
fast_match_byte = ["dep:cssparser-macros"]
fast_match_color = ["dep:phf"]
# Useful for skipping tests when execution is slow, e.g., under miri
skip_long_tests = []
[workspace]
members = [".", "./macros", "./color"]
default-members = [".", "./macros", "./color"]
+1 -1
View File
@@ -172,7 +172,7 @@ pub fn parse_hash_color(value: &[u8]) -> Result<(u8, u8, u8, f32), ()> {
})
}
ascii_case_insensitive_phf_map! {
ascii_case_insensitive_map! {
named_colors -> (u8, u8, u8) = {
"black" => (0, 0, 0),
"silver" => (192, 192, 192),
+35 -1
View File
@@ -84,7 +84,41 @@ pub use crate::serializer::{serialize_identifier, serialize_name, serialize_stri
pub use crate::serializer::{CssStringWriter, ToCss, TokenSerializationType};
pub use crate::tokenizer::{SourceLocation, SourcePosition, Token};
pub use crate::unicode_range::UnicodeRange;
pub use cssparser_macros::*;
#[cfg(feature = "fast_match_byte")]
pub use cssparser_macros::match_byte;
#[cfg(not(feature = "fast_match_byte"))]
#[macro_use]
mod mac {
/// Expand a TokenStream corresponding to the `match_byte` macro.
///
/// ## Example
///
/// ```rust,ignore
/// match_byte! { tokenizer.next_byte_unchecked(),
/// b'a'..b'z' => { ... }
/// b'0'..b'9' => { ... }
/// b'\n' | b'\\' => { ... }
/// foo => { ... }
/// }
/// ```
///
#[macro_export]
macro_rules! match_byte {
($value:expr, $($rest:tt)* ) => {
match $value {
$(
$rest
)+
}
};
}
}
// Re-exporting phf here means that the crate using the ascii_case_insensitive_phf_map macro do
// do not have to depend on phf directly.
#[cfg(feature = "fast_match_color")]
#[doc(hidden)]
pub use phf as _cssparser_internal_phf;
+107 -19
View File
@@ -34,22 +34,34 @@ macro_rules! match_ignore_ascii_case {
( $input:expr,
$(
$( #[$meta: meta] )*
$( $pattern: pat )|+ $( if $guard: expr )? => $then: expr
$( $pattern:literal )|+ $( if $guard: expr )? => $then: expr
),+
$(,_ => $fallback:expr)?
$(,)?
) => {
{
// This dummy module works around the feature gate
// `error[E0658]: procedural macros cannot be expanded to statements`
// by forcing the macro to be in an item context
// rather than expression/statement context,
// even though the macro only expands to items.
mod cssparser_internal {
$crate::_cssparser_internal_max_len! {
$( $( $pattern )+ )+
#[inline(always)]
const fn const_usize_max(a: usize, b: usize) -> usize {
if a > b {
a
} else {
b
}
}
$crate::_cssparser_internal_to_lowercase!($input, cssparser_internal::MAX_LENGTH => lowercase);
const MAX_LENGTH : usize = {
let mut maxlen : usize = 0;
$(
$( #[$meta] )*
// {} is necessary to work around "[E0658]: attributes on expressions are experimental"
{
$( maxlen = const_usize_max(maxlen, $pattern.len()); )+
}
)+
maxlen
};
$crate::_cssparser_internal_to_lowercase!($input, MAX_LENGTH => lowercase);
// "A" is a short string that we know is different for every string pattern,
// since weve verified that none of them include ASCII upper case letters.
match lowercase.unwrap_or("A") {
@@ -57,11 +69,14 @@ macro_rules! match_ignore_ascii_case {
$( #[$meta] )*
$( $pattern )|+ $( if $guard )? => $then,
)+
$(_ => $fallback,)?
}
}
};
}
#[cfg(not(feature = "fast_match_color"))]
#[macro_export]
/// Define a function `$name(&str) -> Option<&'static $ValueType>`
///
/// The function finds a match for the input string
@@ -75,7 +90,7 @@ macro_rules! match_ignore_ascii_case {
/// # fn main() {} // Make doctest not wrap everything in its own main
///
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
/// cssparser::ascii_case_insensitive_phf_map! {
/// cssparser::ascii_case_insensitive_map! {
/// keywords -> (u8, u8, u8) = {
/// "red" => (255, 0, 0),
/// "green" => (0, 255, 0),
@@ -87,6 +102,71 @@ macro_rules! match_ignore_ascii_case {
/// ```
///
/// You can also iterate over the map entries by using `keywords::entries()`.
macro_rules! ascii_case_insensitive_map {
($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr ),+ }) => {
ascii_case_insensitive_map!($name -> $ValueType = { $( $key => $value, )+ })
};
($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr, )+ }) => {
// While the obvious choice for this would be an inner module, it's not possible to
// reference from types from there, see:
// <https://github.com/rust-lang/rust/issues/114369>
//
// So we abuse a struct with static associated functions instead.
#[allow(non_camel_case_types)]
struct $name;
impl $name {
#[allow(dead_code)]
fn entries() -> impl Iterator<Item = (&'static &'static str, &'static $ValueType)> {
[ $((&$key, &$value),)* ].iter().copied()
}
fn get(input: &str) -> Option<&'static $ValueType> {
$crate::match_ignore_ascii_case!(input,
$($key => Some(&$value),)*
_ => None,
)
}
}
}
}
#[cfg(feature = "fast_match_color")]
#[macro_export]
/// Define a function `$name(&str) -> Option<&'static $ValueType>`
///
/// The function finds a match for the input string
/// in a [`phf` map](https://github.com/sfackler/rust-phf)
/// and returns a reference to the corresponding value.
/// Matching is case-insensitive in the ASCII range.
///
/// ## Example:
///
/// ```rust
/// # fn main() {} // Make doctest not wrap everything in its own main
///
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
/// cssparser::ascii_case_insensitive_map! {
/// keywords -> (u8, u8, u8) = {
/// "red" => (255, 0, 0),
/// "green" => (0, 255, 0),
/// "blue" => (0, 0, 255),
/// }
/// }
/// keywords::get(input).cloned()
/// }
/// ```
///
/// You can also iterate over the map entries by using `keywords::entries()`.
macro_rules! ascii_case_insensitive_map {
($($any:tt)+) => {
$crate::ascii_case_insensitive_phf_map!($($any)+);
};
}
/// Fast implementation of `ascii_case_insensitive_map!` using a phf map.
/// See `ascii_case_insensitive_map!` above for docs
#[cfg(feature = "fast_match_color")]
#[macro_export]
macro_rules! ascii_case_insensitive_phf_map {
($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr ),+ }) => {
@@ -95,14 +175,22 @@ macro_rules! ascii_case_insensitive_phf_map {
($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr, )+ }) => {
use $crate::_cssparser_internal_phf as phf;
// See macro above for context.
mod cssparser_internal {
$crate::_cssparser_internal_max_len! {
$( $key )+
#[inline(always)]
const fn const_usize_max(a: usize, b: usize) -> usize {
if a > b {
a
} else {
b
}
}
static MAP: phf::Map<&'static str, $ValueType> = phf::phf_map! {
const MAX_LENGTH : usize = {
let mut maxlen : usize = 0;
$( maxlen = const_usize_max(maxlen, ($key).len()); )+
maxlen
};
static __MAP: phf::Map<&'static str, $ValueType> = phf::phf_map! {
$(
$key => $value,
)*
@@ -118,12 +206,12 @@ macro_rules! ascii_case_insensitive_phf_map {
impl $name {
#[allow(dead_code)]
fn entries() -> impl Iterator<Item = (&'static &'static str, &'static $ValueType)> {
MAP.entries()
__MAP.entries()
}
fn get(input: &str) -> Option<&'static $ValueType> {
$crate::_cssparser_internal_to_lowercase!(input, cssparser_internal::MAX_LENGTH => lowercase);
MAP.get(lowercase?)
$crate::_cssparser_internal_to_lowercase!(input, MAX_LENGTH => lowercase);
__MAP.get(lowercase?)
}
}
}
+6 -6
View File
@@ -20,8 +20,8 @@ pub fn parse_nth<'i>(input: &mut Parser<'i, '_>) -> Result<(i32, i32), BasicPars
} => {
match_ignore_ascii_case! {
unit,
"n" => Ok(parse_b(input, a)?),
"n-" => Ok(parse_signless_b(input, a, -1)?),
"n" => parse_b(input, a),
"n-" => parse_signless_b(input, a, -1),
_ => match parse_n_dash_digits(unit) {
Ok(b) => Ok((a, b)),
Err(()) => {
@@ -35,10 +35,10 @@ pub fn parse_nth<'i>(input: &mut Parser<'i, '_>) -> Result<(i32, i32), BasicPars
match_ignore_ascii_case! { value,
"even" => Ok((2, 0)),
"odd" => Ok((2, 1)),
"n" => Ok(parse_b(input, 1)?),
"-n" => Ok(parse_b(input, -1)?),
"n-" => Ok(parse_signless_b(input, 1, -1)?),
"-n-" => Ok(parse_signless_b(input, -1, -1)?),
"n" => parse_b(input, 1),
"-n" => parse_b(input, -1),
"n-" => parse_signless_b(input, 1, -1),
"-n-" => parse_signless_b(input, -1, -1),
_ => {
let (slice, a) = if let Some(stripped) = value.strip_prefix('-') {
(stripped, -1)
+1 -3
View File
@@ -659,9 +659,7 @@ impl<'i: 't, 't> Parser<'i, 't> {
.input
.cached_token
.as_ref()
.map_or(false, |cached_token| {
cached_token.start_position == token_start_position
});
.is_some_and(|cached_token| cached_token.start_position == token_start_position);
let token = if using_cached_token {
let cached_token = self.input.cached_token.as_ref().unwrap();
self.input.tokenizer.reset(&cached_token.end_state);
+14 -16
View File
@@ -2,11 +2,12 @@
* 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 crate::match_byte;
use dtoa_short::Notation;
use std::fmt::{self, Write};
use std::str;
#[cfg(feature = "fast_match_byte")]
pub use crate::match_byte;
use super::Token;
/// Trait for things the can serialize themselves in CSS syntax.
@@ -32,24 +33,21 @@ fn write_numeric<W>(value: f32, int_value: Option<i32>, has_sign: bool, dest: &m
where
W: fmt::Write,
{
// `value.value >= 0` is true for negative 0.
if has_sign && value.is_sign_positive() {
if value == 0.0 && value.is_sign_negative() {
// Negative zero. Work around #20596.
return dest.write_str("-0");
}
// NOTE: `value.value >= 0` is true for negative 0 but we've dealt with it above.
if has_sign && value >= 0.0 {
dest.write_str("+")?;
}
let notation = if value == 0.0 && value.is_sign_negative() {
// Negative zero. Work around #20596.
dest.write_str("-0")?;
Notation {
decimal_point: false,
scientific: false,
}
} else {
dtoa_short::write(dest, value)?
};
if let Some(v) = int_value {
return write!(dest, "{}", v);
}
if int_value.is_none() && value.fract() == 0. && !notation.decimal_point && !notation.scientific
{
let notation = dtoa_short::write(dest, value)?;
if value.fract() == 0. && !notation.decimal_point && !notation.scientific {
dest.write_str(".0")?;
}
Ok(())
+2 -2
View File
@@ -1085,7 +1085,7 @@ fn one_component_value_to_json(token: Token, input: &mut Parser) -> Value {
/// including in string literals.
#[test]
fn procedural_masquerade_whitespace() {
ascii_case_insensitive_phf_map! {
ascii_case_insensitive_map! {
map -> () = {
" \t\n" => ()
}
@@ -1333,7 +1333,7 @@ fn utf16_columns() {
#[test]
fn servo_define_css_keyword_enum() {
macro_rules! define_css_keyword_enum {
(pub enum $name:ident { $($variant:ident = $css:pat,)+ }) => {
(pub enum $name:ident { $($variant:ident = $css:literal,)+ }) => {
#[derive(PartialEq, Debug)]
pub enum $name {
$($variant),+
+2 -13
View File
@@ -10,19 +10,8 @@ use crate::parser::{ArbitrarySubstitutionFunctions, ParserState};
use std::char;
use std::ops::Range;
#[cfg(not(feature = "dummy_match_byte"))]
use cssparser_macros::match_byte;
#[cfg(feature = "dummy_match_byte")]
macro_rules! match_byte {
($value:expr, $($rest:tt)* ) => {
match $value {
$(
$rest
)+
}
};
}
#[cfg(feature = "fast_match_byte")]
pub use crate::match_byte;
/// One of the pieces the CSS input is broken into.
///