From 44771bf8fd1db2d0b72081baf0d54680c70ceb95c693dbc2635acf86fe8e4f34 Mon Sep 17 00:00:00 2001 From: Wolfgang Rosenauer Date: Fri, 11 Oct 2019 12:48:56 +0000 Subject: [PATCH] - Mozilla Thunderbird 68.1.2 Bugfixes * Some attachments couldn't be opened in messages originating from MS Outlook 2016 * Address book import from CSV * Performance problem in message body search * Ctrl+Enter to send a message would open an attachment if the attachment pane had focus * Calendar: Issues with "Today Pane" start-up * Calendar: Glitches with custom repeat and reminder number input * Calendar: Problems with WCAP provider - add mozilla-bmo1585099.patch to fix build with rust >= 1.38 OBS-URL: https://build.opensuse.org/package/show/mozilla:Factory/MozillaThunderbird?expand=0&rev=496 --- MozillaThunderbird.changes | 16 + MozillaThunderbird.spec | 8 +- compare-locales.tar.xz | 4 +- l10n-68.1.1.tar.xz | 3 - l10n-68.1.2.tar.xz | 3 + mozilla-bmo1585099.patch | 4133 ++++++++++++++++++++++++++ tar_stamps | 4 +- thunderbird-68.1.1.source.tar.xz | 3 - thunderbird-68.1.1.source.tar.xz.asc | 16 - thunderbird-68.1.2.source.tar.xz | 3 + thunderbird-68.1.2.source.tar.xz.asc | 16 + 11 files changed, 4180 insertions(+), 29 deletions(-) delete mode 100644 l10n-68.1.1.tar.xz create mode 100644 l10n-68.1.2.tar.xz create mode 100644 mozilla-bmo1585099.patch delete mode 100644 thunderbird-68.1.1.source.tar.xz delete mode 100644 thunderbird-68.1.1.source.tar.xz.asc create mode 100644 thunderbird-68.1.2.source.tar.xz create mode 100644 thunderbird-68.1.2.source.tar.xz.asc diff --git a/MozillaThunderbird.changes b/MozillaThunderbird.changes index d3439b3..5165773 100644 --- a/MozillaThunderbird.changes +++ b/MozillaThunderbird.changes @@ -1,3 +1,19 @@ +------------------------------------------------------------------- +Thu Oct 10 14:30:09 UTC 2019 - Wolfgang Rosenauer + +- Mozilla Thunderbird 68.1.2 + Bugfixes + * Some attachments couldn't be opened in messages originating from + MS Outlook 2016 + * Address book import from CSV + * Performance problem in message body search + * Ctrl+Enter to send a message would open an attachment if the + attachment pane had focus + * Calendar: Issues with "Today Pane" start-up + * Calendar: Glitches with custom repeat and reminder number input + * Calendar: Problems with WCAP provider +- add mozilla-bmo1585099.patch to fix build with rust >= 1.38 + ------------------------------------------------------------------- Wed Sep 25 11:46:51 UTC 2019 - Wolfgang Rosenauer diff --git a/MozillaThunderbird.spec b/MozillaThunderbird.spec index 1f01c91..96e1a75 100644 --- a/MozillaThunderbird.spec +++ b/MozillaThunderbird.spec @@ -26,11 +26,11 @@ # major 69 # mainver %major.99 %define major 68 -%define mainver %major.1.1 -%define orig_version 68.1.1 +%define mainver %major.1.2 +%define orig_version 68.1.2 %define orig_suffix %{nil} %define update_channel release -%define releasedate 20190924105435 +%define releasedate 20191008153335 %define source_prefix thunderbird-%{mainver} # always build with GCC as SUSE Security Team requires that @@ -178,6 +178,7 @@ Patch21: mozilla-bmo1554971.patch Patch22: mozilla-nestegg-big-endian.patch Patch23: mozilla-bmo1512162.patch Patch24: mozilla-fix-top-level-asm.patch +Patch25: mozilla-bmo1585099.patch Patch100: thunderbird-broken-locales-build.patch %endif # only_print_mozconfig BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -282,6 +283,7 @@ fi %patch22 -p1 %patch23 -p1 %patch24 -p1 +%patch25 -p1 # Thunderbird %patch100 -p1 %endif # only_print_mozconfig diff --git a/compare-locales.tar.xz b/compare-locales.tar.xz index 2bba393..5e4b60a 100644 --- a/compare-locales.tar.xz +++ b/compare-locales.tar.xz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7882c9c5c073a24f48abf4c7ea46070746a49f95ba75d49e7cb8a814cf2ec513 -size 28496 +oid sha256:f8e19a20a0b98e6b292a598734238128270cfb4019eee6f65ed6c9a9dbbc91d6 +size 28540 diff --git a/l10n-68.1.1.tar.xz b/l10n-68.1.1.tar.xz deleted file mode 100644 index 6f49405..0000000 --- a/l10n-68.1.1.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:80110e0c17901459c11b3e716c048259b9a9c1f6d841a5eb3d67e4e13e8626f7 -size 28450164 diff --git a/l10n-68.1.2.tar.xz b/l10n-68.1.2.tar.xz new file mode 100644 index 0000000..486e2d9 --- /dev/null +++ b/l10n-68.1.2.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6878eb1036174dc95be285d7851eeb6848fbb3a3753704df5624b317cbde2b5b +size 28453140 diff --git a/mozilla-bmo1585099.patch b/mozilla-bmo1585099.patch new file mode 100644 index 0000000..a9e9514 --- /dev/null +++ b/mozilla-bmo1585099.patch @@ -0,0 +1,4133 @@ +diff --git a/Cargo.lock b/Cargo.lock +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -736,7 +736,7 @@ + + [[package]] + name = "cssparser" +-version = "0.25.3" ++version = "0.25.5" + source = "registry+https://github.com/rust-lang/crates.io-index" + dependencies = [ + "cssparser-macros 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +@@ -1204,7 +1204,7 @@ + version = "0.0.1" + dependencies = [ + "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +@@ -1681,7 +1681,7 @@ + version = "0.0.1" + dependencies = [ + "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashglobe 0.1.0", + "selectors 0.21.0", +@@ -2667,7 +2667,7 @@ + version = "0.21.0" + dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +@@ -2884,7 +2884,7 @@ + "bindgen 0.49.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fallible 0.0.1", +@@ -2946,7 +2946,7 @@ + dependencies = [ + "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "malloc_size_of 0.0.1", +@@ -2962,7 +2962,7 @@ + version = "0.0.1" + dependencies = [ + "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "geckoservo 0.0.1", +@@ -3137,7 +3137,7 @@ + name = "to_shmem" + version = "0.0.1" + dependencies = [ +- "cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)", ++ "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", + "servo_arc 0.1.1", + "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +@@ -3807,7 +3807,7 @@ + "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" + "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b" + "checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" +-"checksum cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ba1ab4e1814be64bf6b6064ff532db0e34087f11b37706d6c96a21d32478761d" ++"checksum cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e06795910fc2f585a75bdc9690fbcc51e83519f07b6eb981db43944643c04933" + "checksum cssparser-macros 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a5383ae18dbfdeb569ed62019f5bddb2a95cd2d3833313c475a0d014777805" + "checksum cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b6557bdb1dc9647eae1cf7f5601b14cd45fc3c7ccf2df618387416fe542da6ea" + "checksum cstr-macros 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0472c17c83d3ec1af32fb6ee2b3ad56ae0b6e69355d63d1d30602055c34324a8" +diff --git a/third_party/rust/cssparser/.cargo-checksum.json b/third_party/rust/cssparser/.cargo-checksum.json +--- a/third_party/rust/cssparser/.cargo-checksum.json ++++ b/third_party/rust/cssparser/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{"Cargo.toml":"150d450e43bcb9e523941408be883997ecffce7ff5f224329372edfe56334a55","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"b9d6c5dc56ccc267db9e0e2389061dc2524daefa4baed88b36c98efc7a51c2a9","build.rs":"310d6d7b1931ff783a8aa1a4c6baee87b4c9130c858e4694ef69cc96df5e38dc","build/match_byte.rs":"6f7ec4235c9f2da403ea0be9339661ecd8e1f5e1c788cf88a41448b1080c59b8","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"43f996fbd8da54bd8ffa870f5e3610e5ba6e61543f92a129fa6c850e9b10db7e","src/cow_rc_str.rs":"541216f8ef74ee3cc5cbbc1347e5f32ed66588c401851c9a7d68b867aede1de0","src/from_bytes.rs":"331fe63af2123ae3675b61928a69461b5ac77799fff3ce9978c55cf2c558f4ff","src/lib.rs":"a474ee88ef8f73fcb7b7272d426e5eafb4ad10d104797a5a188d1676c8180972","src/macros.rs":"adb9773c157890381556ea83d7942dcc676f99eea71abbb6afeffee1e3f28960","src/nth.rs":"5c70fb542d1376cddab69922eeb4c05e4fcf8f413f27563a2af50f72a47c8f8c","src/parser.rs":"22067562160a1294fa92779b66c25cbccf259a2ef7dcf687c791fecdd020ce7f","src/rules_and_declarations.rs":"622ce07c117a511d40ce595602d4f4730659a59273388f28553d1a2b0fac92ce","src/serializer.rs":"3e2dfc60613f885cb6f99abfc854fde2a1e00de507431bd2e51178b61abfd69b","src/size_of_tests.rs":"385a0d77fbd6f86cb8013fd8d7541886980876a9da1da714bf175954c0e726cf","src/tests.rs":"9d08b3943d453664e01d58e307f79345e240f9f9ce6f8d36a842eff37155563e","src/tokenizer.rs":"adcf5811955e8df57a519e3d1e44fe3afeb5afeb1076daeb8d36fed1abcf1327","src/unicode_range.rs":"ae159d2ebe4123a6666e18dc0362f89b475240a6b7ed5fb6fe21b9e7a4139da8"},"package":"ba1ab4e1814be64bf6b6064ff532db0e34087f11b37706d6c96a21d32478761d"} +\ No newline at end of file ++{"files":{"Cargo.toml":"26e11f3e55baf0de8784dc3ec88771411ceae587c64e162fed3939b87c3cc591","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"b9d6c5dc56ccc267db9e0e2389061dc2524daefa4baed88b36c98efc7a51c2a9","build.rs":"08e4a99d5184b2f22ab93bc0a024fec18dbd8fd38b9db638f19d4defede858ee","build/match_byte.rs":"e8537833ff1599a1bdbd0167f6295af7bd21e42024f32b982af32d58c156685c","docs/404.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","docs/index.html":"025861f76f8d1f6d67c20ab624c6e418f4f824385e2dd8ad8732c4ea563c6a2e","src/color.rs":"8d3017ba8d644172908bd80d35e9be1081db477d2e0b0ea13971e29a466d451f","src/cow_rc_str.rs":"89b5dff5cf80eef3fcff0c11799e54a978d02d8b8963a621fbb999d35e7c03a3","src/from_bytes.rs":"b1cf15c4e975523fef46b575598737a39f3c63e5ce0b2bfd6ec627c69c6ea54a","src/lib.rs":"98b28ca7c72b8d20b3d76ae5b841be87bcadfc89e433ecc95fcf37aa15731442","src/macros.rs":"a50a0a7afa43e099dc008e54956e4c1fdfba2e9795d006b22e9eb45065fed61e","src/nth.rs":"a9d5fa0bd2c3ae7c48c851b9f5508ebdb07affdf5d0737bb8d85a7befab2ef9c","src/parser.rs":"fe2eb2be084923bf362de4b95c029beb21f172ad972a6452c400f640b43a583e","src/rules_and_declarations.rs":"712a5e893169e715bbcd18aac87a18ae728dc6bb922e79b237d34ce7a4548fcf","src/serializer.rs":"151305364cb1f20ea2dc0b3ebfbb77937e616ef4441d5dd3c9abda232f79a7af","src/size_of_tests.rs":"a628cacc876f240ac1bb9e287cdae293bffc4b86d45d9307e4fc2f822e8f3e84","src/tests.rs":"bf97071b691c0b0c932af5813e876142ce707ba57774742dbe60889b1dc54069","src/tokenizer.rs":"0450c38d140382161408a8fca5aac343f5a9405603234095dccd93f680831cb7","src/unicode_range.rs":"c4655c817db0dabb1d55669ac61a56ecf7f6a6c4353cf5b539b13bea6511c3dd"},"package":"e06795910fc2f585a75bdc9690fbcc51e83519f07b6eb981db43944643c04933"} +\ No newline at end of file +diff --git a/third_party/rust/cssparser/Cargo.toml b/third_party/rust/cssparser/Cargo.toml +--- a/third_party/rust/cssparser/Cargo.toml ++++ b/third_party/rust/cssparser/Cargo.toml +@@ -12,7 +12,7 @@ + + [package] + name = "cssparser" +-version = "0.25.3" ++version = "0.25.5" + authors = ["Simon Sapin "] + build = "build.rs" + exclude = ["src/css-parsing-tests/**", "src/big-data-url.css"] +diff --git a/third_party/rust/cssparser/build.rs b/third_party/rust/cssparser/build.rs +--- a/third_party/rust/cssparser/build.rs ++++ b/third_party/rust/cssparser/build.rs +@@ -33,9 +33,12 @@ + println!("cargo:rerun-if-changed={}", input.display()); + + // We have stack overflows on Servo's CI. +- let handle = Builder::new().stack_size(128 * 1024 * 1024).spawn(move || { +- match_byte::expand(&input, &output); +- }).unwrap(); ++ let handle = Builder::new() ++ .stack_size(128 * 1024 * 1024) ++ .spawn(move || { ++ match_byte::expand(&input, &output); ++ }) ++ .unwrap(); + + handle.join().unwrap(); + } +diff --git a/third_party/rust/cssparser/build/match_byte.rs b/third_party/rust/cssparser/build/match_byte.rs +--- a/third_party/rust/cssparser/build/match_byte.rs ++++ b/third_party/rust/cssparser/build/match_byte.rs +@@ -12,18 +12,27 @@ + + use proc_macro2::{Span, TokenStream}; + +-struct MatchByteParser { +-} ++struct MatchByteParser {} + + pub fn expand(from: &Path, to: &Path) { + let mut source = String::new(); +- File::open(from).unwrap().read_to_string(&mut source).unwrap(); ++ File::open(from) ++ .unwrap() ++ .read_to_string(&mut source) ++ .unwrap(); + let ast = syn::parse_file(&source).expect("Parsing rules.rs module"); + let mut m = MatchByteParser {}; + let ast = m.fold_file(ast); + +- let code = ast.into_token_stream().to_string().replace("{ ", "{\n").replace(" }", "\n}"); +- File::create(to).unwrap().write_all(code.as_bytes()).unwrap(); ++ let code = ast ++ .into_token_stream() ++ .to_string() ++ .replace("{ ", "{\n") ++ .replace(" }", "\n}"); ++ File::create(to) ++ .unwrap() ++ .write_all(code.as_bytes()) ++ .unwrap(); + } + + struct MatchByte { +@@ -45,7 +54,7 @@ + arms.push(input.call(syn::Arm::parse)?); + } + arms +- } ++ }, + }) + } + } +@@ -55,15 +64,13 @@ + syn::Expr::Lit(syn::ExprLit { ref lit, .. }) => { + if let syn::Lit::Byte(ref byte) = *lit { + byte.value() +- } +- else { ++ } else { + panic!("Found a pattern that wasn't a byte") + } +- }, ++ } + _ => unreachable!(), + } + } +- + + /// Expand a TokenStream corresponding to the `match_byte` macro. + /// +@@ -93,12 +100,12 @@ + + for pat in &arm.pats { + match pat { +- &syn::Pat::Lit(syn::PatLit{ref expr}) => { ++ &syn::Pat::Lit(syn::PatLit { ref expr }) => { + let value = get_byte_from_expr_lit(expr); + if table[value as usize] == 0 { + table[value as usize] = case_id as u8; + } +- }, ++ } + &syn::Pat::Range(syn::PatRange { ref lo, ref hi, .. }) => { + let lo = get_byte_from_expr_lit(lo); + let hi = get_byte_from_expr_lit(hi); +@@ -110,14 +117,14 @@ + if table[hi as usize] == 0 { + table[hi as usize] = case_id as u8; + } +- }, ++ } + &syn::Pat::Wild(_) => { + for byte in table.iter_mut() { + if *byte == 0 { + *byte = case_id as u8; + } + } +- }, ++ } + &syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => { + assert_eq!(wildcard, None); + wildcard = Some(ident); +@@ -126,7 +133,7 @@ + *byte = case_id as u8; + } + } +- }, ++ } + _ => { + panic!("Unexpected pattern: {:?}. Buggy code ?", pat); + } +@@ -159,11 +166,14 @@ + impl Fold for MatchByteParser { + fn fold_stmt(&mut self, stmt: syn::Stmt) -> syn::Stmt { + match stmt { +- syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro{ ref mac, .. })) => { ++ syn::Stmt::Item(syn::Item::Macro(syn::ItemMacro { ref mac, .. })) => { + if mac.path == parse_quote!(match_byte) { +- return syn::fold::fold_stmt(self, syn::Stmt::Expr(expand_match_byte(&mac.tts))) ++ return syn::fold::fold_stmt( ++ self, ++ syn::Stmt::Expr(expand_match_byte(&mac.tts)), ++ ); + } +- }, ++ } + _ => {} + } + +@@ -172,11 +182,11 @@ + + fn fold_expr(&mut self, expr: syn::Expr) -> syn::Expr { + match expr { +- syn::Expr::Macro(syn::ExprMacro{ ref mac, .. }) => { ++ syn::Expr::Macro(syn::ExprMacro { ref mac, .. }) => { + if mac.path == parse_quote!(match_byte) { +- return syn::fold::fold_expr(self, expand_match_byte(&mac.tts)) ++ return syn::fold::fold_expr(self, expand_match_byte(&mac.tts)); + } +- }, ++ } + _ => {} + } + +diff --git a/third_party/rust/cssparser/src/color.rs b/third_party/rust/cssparser/src/color.rs +--- a/third_party/rust/cssparser/src/color.rs ++++ b/third_party/rust/cssparser/src/color.rs +@@ -2,10 +2,10 @@ + * 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::f32::consts::PI; + use std::fmt; +-use std::f32::consts::PI; +- +-use super::{Token, Parser, ToCss, ParseError, BasicParseError}; ++ ++use super::{BasicParseError, ParseError, Parser, ToCss, Token}; + + #[cfg(feature = "serde")] + use serde::{Deserialize, Deserializer, Serialize, Serializer}; +@@ -47,7 +47,12 @@ + /// Same thing, but with `u8` values instead of floats in the 0 to 1 range. + #[inline] + pub fn new(red: u8, green: u8, blue: u8, alpha: u8) -> Self { +- RGBA { red: red, green: green, blue: blue, alpha: alpha } ++ RGBA { ++ red: red, ++ green: green, ++ blue: blue, ++ alpha: alpha, ++ } + } + + /// Returns the red channel in a floating point number form, from 0 to 1. +@@ -78,7 +83,8 @@ + #[cfg(feature = "serde")] + impl Serialize for RGBA { + fn serialize(&self, serializer: S) -> Result +- where S: Serializer ++ where ++ S: Serializer, + { + (self.red, self.green, self.blue, self.alpha).serialize(serializer) + } +@@ -87,7 +93,8 @@ + #[cfg(feature = "serde")] + impl<'de> Deserialize<'de> for RGBA { + fn deserialize(deserializer: D) -> Result +- where D: Deserializer<'de> ++ where ++ D: Deserializer<'de>, + { + let (r, g, b, a) = Deserialize::deserialize(deserializer)?; + Ok(RGBA::new(r, g, b, a)) +@@ -99,7 +106,8 @@ + + impl ToCss for RGBA { + fn to_css(&self, dest: &mut W) -> fmt::Result +- where W: fmt::Write, ++ where ++ W: fmt::Write, + { + let serialize_alpha = self.alpha != 255; + +@@ -137,7 +145,10 @@ + known_heap_size!(0, Color); + + impl ToCss for Color { +- fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { ++ fn to_css(&self, dest: &mut W) -> fmt::Result ++ where ++ W: fmt::Write, ++ { + match *self { + Color::CurrentColor => dest.write_str("currentcolor"), + Color::RGBA(ref rgba) => rgba.to_css(dest), +@@ -210,7 +221,9 @@ + let location = input.current_source_location(); + Ok(match *input.next()? { + Token::Number { value, .. } => AngleOrNumber::Number { value }, +- Token::Dimension { value: v, ref unit, .. } => { ++ Token::Dimension { ++ value: v, ref unit, .. ++ } => { + let degrees = match_ignore_ascii_case! { &*unit, + "deg" => v, + "grad" => v * 360. / 400., +@@ -221,7 +234,7 @@ + + AngleOrNumber::Angle { degrees } + } +- ref t => return Err(location.new_unexpected_token_error(t.clone())) ++ ref t => return Err(location.new_unexpected_token_error(t.clone())), + }) + } + +@@ -252,7 +265,7 @@ + Ok(match *input.next()? { + Token::Number { value, .. } => NumberOrPercentage::Number { value }, + Token::Percentage { unit_value, .. } => NumberOrPercentage::Percentage { unit_value }, +- ref t => return Err(location.new_unexpected_token_error(t.clone())) ++ ref t => return Err(location.new_unexpected_token_error(t.clone())), + }) + } + } +@@ -279,21 +292,20 @@ + match token { + Token::Hash(ref value) | Token::IDHash(ref value) => { + Color::parse_hash(value.as_bytes()) +- }, ++ } + Token::Ident(ref value) => parse_color_keyword(&*value), + Token::Function(ref name) => { + return input.parse_nested_block(|arguments| { + parse_color_function(component_parser, &*name, arguments) + }) + } +- _ => Err(()) +- }.map_err(|()| location.new_unexpected_token_error(token)) ++ _ => Err(()), ++ } ++ .map_err(|()| location.new_unexpected_token_error(token)) + } + + /// Parse a value, per CSS Color Module Level 3. +- pub fn parse<'i, 't>( +- input: &mut Parser<'i, 't>, +- ) -> Result> { ++ pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { + let component_parser = DefaultComponentParser; + Self::parse_with(&component_parser, input).map_err(ParseError::basic) + } +@@ -306,25 +318,25 @@ + from_hex(value[0])? * 16 + from_hex(value[1])?, + from_hex(value[2])? * 16 + from_hex(value[3])?, + from_hex(value[4])? * 16 + from_hex(value[5])?, +- from_hex(value[6])? * 16 + from_hex(value[7])?), +- ), ++ from_hex(value[6])? * 16 + from_hex(value[7])?, ++ )), + 6 => Ok(rgb( + from_hex(value[0])? * 16 + from_hex(value[1])?, + from_hex(value[2])? * 16 + from_hex(value[3])?, +- from_hex(value[4])? * 16 + from_hex(value[5])?), +- ), ++ from_hex(value[4])? * 16 + from_hex(value[5])?, ++ )), + 4 => Ok(rgba( + from_hex(value[0])? * 17, + from_hex(value[1])? * 17, + from_hex(value[2])? * 17, +- from_hex(value[3])? * 17), +- ), ++ from_hex(value[3])? * 17, ++ )), + 3 => Ok(rgb( + from_hex(value[0])? * 17, + from_hex(value[1])? * 17, +- from_hex(value[2])? * 17), +- ), +- _ => Err(()) ++ from_hex(value[2])? * 17, ++ )), ++ _ => Err(()), + } + } + } +@@ -338,7 +350,6 @@ + fn rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Color { + Color::RGBA(RGBA::new(red, green, blue, alpha)) + } +- + + /// Return the named color with the given name. + /// +@@ -355,7 +366,7 @@ + blue: $blue, + alpha: 255, + }) +- } ++ }; + } + ascii_case_insensitive_phf_map! { + keyword -> Color = { +@@ -516,14 +527,13 @@ + keyword(ident).cloned().ok_or(()) + } + +- + #[inline] + fn from_hex(c: u8) -> Result { + match c { +- b'0' ... b'9' => Ok(c - b'0'), +- b'a' ... b'f' => Ok(c - b'a' + 10), +- b'A' ... b'F' => Ok(c - b'A' + 10), +- _ => Err(()) ++ b'0'...b'9' => Ok(c - b'0'), ++ b'a'...b'f' => Ok(c - b'a' + 10), ++ b'A'...b'F' => Ok(c - b'A' + 10), ++ _ => Err(()), + } + } + +@@ -553,7 +563,7 @@ + fn parse_color_function<'i, 't, ComponentParser>( + component_parser: &ComponentParser, + name: &str, +- arguments: &mut Parser<'i, 't> ++ arguments: &mut Parser<'i, 't>, + ) -> Result> + where + ComponentParser: ColorComponentParser<'i>, +@@ -570,7 +580,11 @@ + } else { + arguments.expect_delim('/')?; + }; +- clamp_unit_f32(component_parser.parse_number_or_percentage(arguments)?.unit_value()) ++ clamp_unit_f32( ++ component_parser ++ .parse_number_or_percentage(arguments)? ++ .unit_value(), ++ ) + } else { + 255 + }; +@@ -579,11 +593,10 @@ + Ok(rgba(red, green, blue, alpha)) + } + +- + #[inline] + fn parse_rgb_components_rgb<'i, 't, ComponentParser>( + component_parser: &ComponentParser, +- arguments: &mut Parser<'i, 't> ++ arguments: &mut Parser<'i, 't>, + ) -> Result<(u8, u8, u8, bool), ParseError<'i, ComponentParser::Error>> + where + ComponentParser: ColorComponentParser<'i>, +@@ -591,15 +604,11 @@ + // Either integers or percentages, but all the same type. + // https://drafts.csswg.org/css-color/#rgb-functions + let (red, is_number) = match component_parser.parse_number_or_percentage(arguments)? { +- NumberOrPercentage::Number { value } => { +- (clamp_floor_256_f32(value), true) +- } +- NumberOrPercentage::Percentage { unit_value } => { +- (clamp_unit_f32(unit_value), false) +- } ++ NumberOrPercentage::Number { value } => (clamp_floor_256_f32(value), true), ++ NumberOrPercentage::Percentage { unit_value } => (clamp_unit_f32(unit_value), false), + }; + +- let uses_commas = arguments.try(|i| i.expect_comma()).is_ok(); ++ let uses_commas = arguments.try_parse(|i| i.expect_comma()).is_ok(); + + let green; + let blue; +@@ -623,7 +632,7 @@ + #[inline] + fn parse_rgb_components_hsl<'i, 't, ComponentParser>( + component_parser: &ComponentParser, +- arguments: &mut Parser<'i, 't> ++ arguments: &mut Parser<'i, 't>, + ) -> Result<(u8, u8, u8, bool), ParseError<'i, ComponentParser::Error>> + where + ComponentParser: ColorComponentParser<'i>, +@@ -638,7 +647,7 @@ + + // Saturation and lightness are clamped to 0% ... 100% + // https://drafts.csswg.org/css-color/#the-hsl-notation +- let uses_commas = arguments.try(|i| i.expect_comma()).is_ok(); ++ let uses_commas = arguments.try_parse(|i| i.expect_comma()).is_ok(); + + let saturation = component_parser.parse_percentage(arguments)?; + let saturation = saturation.max(0.).min(1.); +@@ -653,16 +662,28 @@ + // https://drafts.csswg.org/css-color/#hsl-color + // except with h pre-multiplied by 3, to avoid some rounding errors. + fn hue_to_rgb(m1: f32, m2: f32, mut h3: f32) -> f32 { +- if h3 < 0. { h3 += 3. } +- if h3 > 3. { h3 -= 3. } +- +- if h3 * 2. < 1. { m1 + (m2 - m1) * h3 * 2. } +- else if h3 * 2. < 3. { m2 } +- else if h3 < 2. { m1 + (m2 - m1) * (2. - h3) * 2. } +- else { m1 } +- } +- let m2 = if lightness <= 0.5 { lightness * (saturation + 1.) } +- else { lightness + saturation - lightness * saturation }; ++ if h3 < 0. { ++ h3 += 3. ++ } ++ if h3 > 3. { ++ h3 -= 3. ++ } ++ ++ if h3 * 2. < 1. { ++ m1 + (m2 - m1) * h3 * 2. ++ } else if h3 * 2. < 3. { ++ m2 ++ } else if h3 < 2. { ++ m1 + (m2 - m1) * (2. - h3) * 2. ++ } else { ++ m1 ++ } ++ } ++ let m2 = if lightness <= 0.5 { ++ lightness * (saturation + 1.) ++ } else { ++ lightness + saturation - lightness * saturation ++ }; + let m1 = lightness * 2. - m2; + let hue_times_3 = hue * 3.; + let red = clamp_unit_f32(hue_to_rgb(m1, m2, hue_times_3 + 1.)); +diff --git a/third_party/rust/cssparser/src/cow_rc_str.rs b/third_party/rust/cssparser/src/cow_rc_str.rs +--- a/third_party/rust/cssparser/src/cow_rc_str.rs ++++ b/third_party/rust/cssparser/src/cow_rc_str.rs +@@ -103,16 +103,12 @@ + fn clone(&self) -> Self { + match self.unpack() { + Err(ptr) => { +- let rc = unsafe { +- Rc::from_raw(ptr) +- }; ++ let rc = unsafe { Rc::from_raw(ptr) }; + let new_rc = rc.clone(); +- mem::forget(rc); // Don’t actually take ownership of this strong reference ++ mem::forget(rc); // Don’t actually take ownership of this strong reference + CowRcStr::from_rc(new_rc) + } +- Ok(_) => { +- CowRcStr { ..*self } +- } ++ Ok(_) => CowRcStr { ..*self }, + } + } + } +@@ -121,9 +117,7 @@ + #[inline] + fn drop(&mut self) { + if let Err(ptr) = self.unpack() { +- mem::drop(unsafe { +- Rc::from_raw(ptr) +- }) ++ mem::drop(unsafe { Rc::from_raw(ptr) }) + } + } + } +@@ -133,9 +127,7 @@ + + #[inline] + fn deref(&self) -> &str { +- self.unpack().unwrap_or_else(|ptr| unsafe { +- &**ptr +- }) ++ self.unpack().unwrap_or_else(|ptr| unsafe { &**ptr }) + } + } + +diff --git a/third_party/rust/cssparser/src/from_bytes.rs b/third_party/rust/cssparser/src/from_bytes.rs +--- a/third_party/rust/cssparser/src/from_bytes.rs ++++ b/third_party/rust/cssparser/src/from_bytes.rs +@@ -17,7 +17,6 @@ + fn is_utf16_be_or_le(encoding: &Self::Encoding) -> bool; + } + +- + /// Determine the character encoding of a CSS stylesheet. + /// + /// This is based on the presence of a BOM (Byte Order Mark), an `@charset` rule, and +@@ -30,31 +29,32 @@ + /// (https://drafts.csswg.org/css-syntax/#environment-encoding), if any. + /// + /// Returns the encoding to use. +-pub fn stylesheet_encoding(css: &[u8], protocol_encoding_label: Option<&[u8]>, +- environment_encoding: Option) +- -> E::Encoding +- where E: EncodingSupport { ++pub fn stylesheet_encoding( ++ css: &[u8], ++ protocol_encoding_label: Option<&[u8]>, ++ environment_encoding: Option, ++) -> E::Encoding ++where ++ E: EncodingSupport, ++{ + // https://drafts.csswg.org/css-syntax/#the-input-byte-stream +- match protocol_encoding_label { +- None => (), +- Some(label) => match E::from_label(label) { +- None => (), +- Some(protocol_encoding) => return protocol_encoding +- } +- } ++ if let Some(label) = protocol_encoding_label { ++ if let Some(protocol_encoding) = E::from_label(label) { ++ return protocol_encoding; ++ }; ++ }; ++ + let prefix = b"@charset \""; + if css.starts_with(prefix) { + let rest = &css[prefix.len()..]; +- match rest.iter().position(|&b| b == b'"') { +- None => (), +- Some(label_length) => if rest[label_length..].starts_with(b"\";") { ++ if let Some(label_length) = rest.iter().position(|&b| b == b'"') { ++ if rest[label_length..].starts_with(b"\";") { + let label = &rest[..label_length]; +- match E::from_label(label) { +- None => (), +- Some(charset_encoding) => if E::is_utf16_be_or_le(&charset_encoding) { +- return E::utf8() ++ if let Some(charset_encoding) = E::from_label(label) { ++ if E::is_utf16_be_or_le(&charset_encoding) { ++ return E::utf8(); + } else { +- return charset_encoding ++ return charset_encoding; + } + } + } +diff --git a/third_party/rust/cssparser/src/lib.rs b/third_party/rust/cssparser/src/lib.rs +--- a/third_party/rust/cssparser/src/lib.rs ++++ b/third_party/rust/cssparser/src/lib.rs +@@ -4,7 +4,6 @@ + + #![crate_name = "cssparser"] + #![crate_type = "rlib"] +- + #![cfg_attr(feature = "bench", feature(test))] + #![deny(missing_docs)] + +@@ -32,7 +31,7 @@ + + * Any `Err(())` return value must be propagated. + This happens by definition for tail calls, +- and can otherwise be done with the `try!` macro. ++ and can otherwise be done with the `?` operator. + * Or the call must be wrapped in a `Parser::try` call. + `try` takes a closure that takes a `Parser` and returns a `Result`, + calls it once, +@@ -46,7 +45,7 @@ + // 'none' | + fn parse_background_image(context: &ParserContext, input: &mut Parser) + -> Result, ()> { +- if input.try(|input| input.expect_ident_matching("none")).is_ok() { ++ if input.try_parse(|input| input.expect_ident_matching("none")).is_ok() { + Ok(None) + } else { + Image::parse(context, input).map(Some) // tail call +@@ -58,50 +57,68 @@ + // [ | ] [ | ]? + fn parse_border_spacing(_context: &ParserContext, input: &mut Parser) + -> Result<(LengthOrPercentage, LengthOrPercentage), ()> { +- let first = try!(LengthOrPercentage::parse); +- let second = input.try(LengthOrPercentage::parse).unwrap_or(first); ++ let first = LengthOrPercentage::parse?; ++ let second = input.try_parse(LengthOrPercentage::parse).unwrap_or(first); + (first, second) + } + ``` + + */ + +-#![recursion_limit="200"] // For color::parse_color_keyword ++#![recursion_limit = "200"] // For color::parse_color_keyword + + extern crate dtoa_short; + extern crate itoa; +-#[macro_use] extern crate cssparser_macros; +-#[macro_use] extern crate matches; +-#[macro_use] extern crate procedural_masquerade; +-#[doc(hidden)] pub extern crate phf as _internal__phf; +-#[cfg(test)] extern crate encoding_rs; +-#[cfg(test)] extern crate difference; +-#[cfg(test)] extern crate rustc_serialize; +-#[cfg(feature = "serde")] extern crate serde; +-#[cfg(feature = "heapsize")] #[macro_use] extern crate heapsize; ++#[macro_use] ++extern crate cssparser_macros; ++#[macro_use] ++extern crate matches; ++#[macro_use] ++extern crate procedural_masquerade; ++#[cfg(test)] ++extern crate difference; ++#[cfg(test)] ++extern crate encoding_rs; ++#[doc(hidden)] ++pub extern crate phf as _internal__phf; ++#[cfg(test)] ++extern crate rustc_serialize; ++#[cfg(feature = "serde")] ++extern crate serde; ++#[cfg(feature = "heapsize")] ++#[macro_use] ++extern crate heapsize; + extern crate smallvec; + + pub use cssparser_macros::*; + +-pub use tokenizer::{Token, SourcePosition, SourceLocation}; +-pub use rules_and_declarations::{parse_important}; +-pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration}; +-pub use rules_and_declarations::{RuleListParser, parse_one_rule}; +-pub use rules_and_declarations::{AtRuleType, QualifiedRuleParser, AtRuleParser}; ++pub use color::{ ++ parse_color_keyword, AngleOrNumber, Color, ColorComponentParser, NumberOrPercentage, RGBA, ++}; ++pub use cow_rc_str::CowRcStr; + pub use from_bytes::{stylesheet_encoding, EncodingSupport}; +-pub use color::{RGBA, Color, parse_color_keyword, AngleOrNumber, NumberOrPercentage, ColorComponentParser}; + pub use nth::parse_nth; +-pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_name, serialize_string, TokenSerializationType}; +-pub use parser::{Parser, Delimiter, Delimiters, ParserState, ParserInput}; +-pub use parser::{ParseError, ParseErrorKind, BasicParseError, BasicParseErrorKind}; ++pub use parser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind}; ++pub use parser::{Delimiter, Delimiters, Parser, ParserInput, ParserState}; ++pub use rules_and_declarations::parse_important; ++pub use rules_and_declarations::{parse_one_declaration, DeclarationListParser, DeclarationParser}; ++pub use rules_and_declarations::{parse_one_rule, RuleListParser}; ++pub use rules_and_declarations::{AtRuleParser, AtRuleType, QualifiedRuleParser}; ++pub use serializer::{ ++ serialize_identifier, serialize_name, serialize_string, CssStringWriter, ToCss, ++ TokenSerializationType, ++}; ++pub use tokenizer::{SourceLocation, SourcePosition, Token}; + pub use unicode_range::UnicodeRange; +-pub use cow_rc_str::CowRcStr; + + // For macros +-#[doc(hidden)] pub use macros::_internal__to_lowercase; ++#[doc(hidden)] ++pub use macros::_internal__to_lowercase; + + // For macros when used in this crate. Unsure how $crate works with procedural-masquerade. +-mod cssparser { pub use _internal__phf; } ++mod cssparser { ++ pub use _internal__phf; ++} + + #[macro_use] + mod macros; +@@ -115,13 +132,15 @@ + mod tokenizer { + include!(concat!(env!("OUT_DIR"), "/tokenizer.rs")); + } ++mod color; ++mod cow_rc_str; ++mod from_bytes; ++mod nth; + mod parser; +-mod from_bytes; +-mod color; +-mod nth; + mod serializer; + mod unicode_range; +-mod cow_rc_str; + +-#[cfg(test)] mod tests; +-#[cfg(test)] mod size_of_tests; ++#[cfg(test)] ++mod size_of_tests; ++#[cfg(test)] ++mod tests; +diff --git a/third_party/rust/cssparser/src/macros.rs b/third_party/rust/cssparser/src/macros.rs +--- a/third_party/rust/cssparser/src/macros.rs ++++ b/third_party/rust/cssparser/src/macros.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/. */ + +-/// See docs of the `procedural-masquerade` crate. ++// See docs of the `procedural-masquerade` crate. + define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro); + + /// Expands to a `match` expression with string patterns, +@@ -114,12 +114,10 @@ + // which initializes with `copy_from_slice` the part of the buffer it uses, + // before it uses it. + #[allow(unsafe_code)] +- let mut buffer: [u8; $BUFFER_SIZE] = unsafe { +- ::std::mem::uninitialized() +- }; ++ let mut buffer: [u8; $BUFFER_SIZE] = unsafe { ::std::mem::uninitialized() }; + let input: &str = $input; + let $output = $crate::_internal__to_lowercase(&mut buffer, input); +- } ++ }; + } + + /// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros. +@@ -134,12 +132,10 @@ + if let Some(buffer) = buffer.get_mut(..input.len()) { + if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) { + buffer.copy_from_slice(input.as_bytes()); +- ::std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]); ++ buffer[first_uppercase..].make_ascii_lowercase(); + // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8) + // then lowercased (which preserves UTF-8 well-formedness) +- unsafe { +- Some(::std::str::from_utf8_unchecked(buffer)) +- } ++ unsafe { Some(::std::str::from_utf8_unchecked(buffer)) } + } else { + // Input is already lower-case + Some(input) +diff --git a/third_party/rust/cssparser/src/nth.rs b/third_party/rust/cssparser/src/nth.rs +--- a/third_party/rust/cssparser/src/nth.rs ++++ b/third_party/rust/cssparser/src/nth.rs +@@ -2,10 +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/. */ + +-#[allow(unused_imports)] use std::ascii::AsciiExt; +- +-use super::{Token, Parser, ParserInput, BasicParseError}; +- ++use super::{BasicParseError, Parser, ParserInput, Token}; + + /// Parse the *An+B* notation, as found in the `:nth-child()` selector. + /// The input is typically the arguments of a function, +@@ -14,14 +11,18 @@ + pub fn parse_nth<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(i32, i32), BasicParseError<'i>> { + // FIXME: remove .clone() when lifetimes are non-lexical. + match input.next()?.clone() { +- Token::Number { int_value: Some(b), .. } => { +- Ok((0, b)) +- } +- Token::Dimension { int_value: Some(a), unit, .. } => { ++ Token::Number { ++ int_value: Some(b), .. ++ } => Ok((0, b)), ++ Token::Dimension { ++ int_value: Some(a), ++ unit, ++ .. ++ } => { + match_ignore_ascii_case! { + &unit, +- "n" => Ok(try!(parse_b(input, a))), +- "n-" => Ok(try!(parse_signless_b(input, a, -1))), ++ "n" => Ok(parse_b(input, a)?), ++ "n-" => Ok(parse_signless_b(input, a, -1)?), + _ => match parse_n_dash_digits(&*unit) { + Ok(b) => Ok((a, b)), + Err(()) => Err(input.new_basic_unexpected_token_error(Token::Ident(unit.clone()))) +@@ -32,10 +33,10 @@ + match_ignore_ascii_case! { &value, + "even" => Ok((2, 0)), + "odd" => Ok((2, 1)), +- "n" => Ok(try!(parse_b(input, 1))), +- "-n" => Ok(try!(parse_b(input, -1))), +- "n-" => Ok(try!(parse_signless_b(input, 1, -1))), +- "-n-" => Ok(try!(parse_signless_b(input, -1, -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)?), + _ => { + let (slice, a) = if value.starts_with("-") { + (&value[1..], -1) +@@ -67,13 +68,16 @@ + } + } + +- + fn parse_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32) -> Result<(i32, i32), BasicParseError<'i>> { + let start = input.state(); + match input.next() { + Ok(&Token::Delim('+')) => parse_signless_b(input, a, 1), + Ok(&Token::Delim('-')) => parse_signless_b(input, a, -1), +- Ok(&Token::Number { has_sign: true, int_value: Some(b), .. }) => Ok((a, b)), ++ Ok(&Token::Number { ++ has_sign: true, ++ int_value: Some(b), ++ .. ++ }) => Ok((a, b)), + _ => { + input.reset(&start); + Ok((a, 0)) +@@ -81,21 +85,29 @@ + } + } + +-fn parse_signless_b<'i, 't>(input: &mut Parser<'i, 't>, a: i32, b_sign: i32) -> Result<(i32, i32), BasicParseError<'i>> { ++fn parse_signless_b<'i, 't>( ++ input: &mut Parser<'i, 't>, ++ a: i32, ++ b_sign: i32, ++) -> Result<(i32, i32), BasicParseError<'i>> { + // FIXME: remove .clone() when lifetimes are non-lexical. + match input.next()?.clone() { +- Token::Number { has_sign: false, int_value: Some(b), .. } => Ok((a, b_sign * b)), +- token => Err(input.new_basic_unexpected_token_error(token)) ++ Token::Number { ++ has_sign: false, ++ int_value: Some(b), ++ .. ++ } => Ok((a, b_sign * b)), ++ token => Err(input.new_basic_unexpected_token_error(token)), + } + } + + fn parse_n_dash_digits(string: &str) -> Result { + let bytes = string.as_bytes(); + if bytes.len() >= 3 +- && bytes[..2].eq_ignore_ascii_case(b"n-") +- && bytes[2..].iter().all(|&c| matches!(c, b'0'...b'9')) ++ && bytes[..2].eq_ignore_ascii_case(b"n-") ++ && bytes[2..].iter().all(|&c| matches!(c, b'0'...b'9')) + { +- Ok(parse_number_saturate(&string[1..]).unwrap()) // Include the minus sign ++ Ok(parse_number_saturate(&string[1..]).unwrap()) // Include the minus sign + } else { + Err(()) + } +@@ -104,14 +116,17 @@ + fn parse_number_saturate(string: &str) -> Result { + let mut input = ParserInput::new(string); + let mut parser = Parser::new(&mut input); +- let int = if let Ok(&Token::Number {int_value: Some(int), ..}) +- = parser.next_including_whitespace_and_comments() { ++ let int = if let Ok(&Token::Number { ++ int_value: Some(int), ++ .. ++ }) = parser.next_including_whitespace_and_comments() ++ { + int + } else { +- return Err(()) ++ return Err(()); + }; + if !parser.is_exhausted() { +- return Err(()) ++ return Err(()); + } + Ok(int) + } +diff --git a/third_party/rust/cssparser/src/parser.rs b/third_party/rust/cssparser/src/parser.rs +--- a/third_party/rust/cssparser/src/parser.rs ++++ b/third_party/rust/cssparser/src/parser.rs +@@ -4,11 +4,9 @@ + + use cow_rc_str::CowRcStr; + use smallvec::SmallVec; ++use std::ops::BitOr; + use std::ops::Range; +-#[allow(unused_imports)] use std::ascii::AsciiExt; +-use std::ops::BitOr; +-use tokenizer::{Token, Tokenizer, SourcePosition, SourceLocation}; +- ++use tokenizer::{SourceLocation, SourcePosition, Token, Tokenizer}; + + /// A capture of the internal state of a `Parser` (including the position within the input), + /// obtained from the `Parser::position` method. +@@ -114,7 +112,10 @@ + + impl<'i, T> ParseErrorKind<'i, T> { + /// Like `std::convert::Into::into` +- pub fn into(self) -> ParseErrorKind<'i, U> where T: Into { ++ pub fn into(self) -> ParseErrorKind<'i, U> ++ where ++ T: Into, ++ { + match self { + ParseErrorKind::Basic(basic) => ParseErrorKind::Basic(basic), + ParseErrorKind::Custom(custom) => ParseErrorKind::Custom(custom.into()), +@@ -144,7 +145,10 @@ + } + + /// Like `std::convert::Into::into` +- pub fn into(self) -> ParseError<'i, U> where T: Into { ++ pub fn into(self) -> ParseError<'i, U> ++ where ++ T: Into, ++ { + ParseError { + kind: self.kind.into(), + location: self.location, +@@ -199,7 +203,6 @@ + stop_before: Delimiters, + } + +- + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + pub(crate) enum BlockType { + Parenthesis, +@@ -207,15 +210,13 @@ + CurlyBracket, + } + +- + impl BlockType { + fn opening(token: &Token) -> Option { + match *token { +- Token::Function(_) | +- Token::ParenthesisBlock => Some(BlockType::Parenthesis), ++ Token::Function(_) | Token::ParenthesisBlock => Some(BlockType::Parenthesis), + Token::SquareBracketBlock => Some(BlockType::SquareBracket), + Token::CurlyBracketBlock => Some(BlockType::CurlyBracket), +- _ => None ++ _ => None, + } + } + +@@ -224,11 +225,10 @@ + Token::CloseParenthesis => Some(BlockType::Parenthesis), + Token::CloseSquareBracket => Some(BlockType::SquareBracket), + Token::CloseCurlyBracket => Some(BlockType::CurlyBracket), +- _ => None +- } +- } +-} +- ++ _ => None, ++ } ++ } ++} + + /// A set of characters, to be used with the `Parser::parse_until*` methods. + /// +@@ -273,7 +273,9 @@ + + #[inline] + fn bitor(self, other: Delimiters) -> Delimiters { +- Delimiters { bits: self.bits | other.bits } ++ Delimiters { ++ bits: self.bits | other.bits, ++ } + } + } + +@@ -338,16 +340,21 @@ + } + + /// Check whether the input is exhausted. That is, if `.next()` would return a token. +- /// Return a `Result` so that the `try!` macro can be used: `try!(input.expect_exhausted())` ++ /// Return a `Result` so that the `?` operator can be used: `input.expect_exhausted()?` + /// + /// This ignores whitespace and comments. + #[inline] + pub fn expect_exhausted(&mut self) -> Result<(), BasicParseError<'i>> { + let start = self.state(); + let result = match self.next() { +- Err(BasicParseError { kind: BasicParseErrorKind::EndOfInput, .. }) => Ok(()), ++ Err(BasicParseError { ++ kind: BasicParseErrorKind::EndOfInput, ++ .. ++ }) => Ok(()), + Err(e) => unreachable!("Unexpected error encountered: {:?}", e), +- Ok(t) => Err(start.source_location().new_basic_unexpected_token_error(t.clone())), ++ Ok(t) => Err(start ++ .source_location() ++ .new_basic_unexpected_token_error(t.clone())), + }; + self.reset(&start); + result +@@ -426,7 +433,7 @@ + pub fn new_error_for_next_token(&mut self) -> ParseError<'i, E> { + let token = match self.next() { + Ok(token) => token.clone(), +- Err(e) => return e.into() ++ Err(e) => return e.into(), + }; + self.new_error(BasicParseErrorKind::UnexpectedToken(token)) + } +@@ -438,7 +445,7 @@ + pub fn state(&self) -> ParserState { + ParserState { + at_start_of: self.at_start_of, +- .. self.input.tokenizer.state() ++ ..self.input.tokenizer.state() + } + } + +@@ -465,7 +472,7 @@ + pub(crate) fn next_byte(&self) -> Option { + let byte = self.input.tokenizer.next_byte(); + if self.stop_before.contains(Delimiters::from_byte(byte)) { +- return None ++ return None; + } + byte + } +@@ -493,6 +500,15 @@ + #[inline] + pub fn seen_var_or_env_functions(&mut self) -> bool { + self.input.tokenizer.seen_var_or_env_functions() ++ } ++ ++ /// The old name of `try_parse`, which requires raw identifiers in the Rust 2018 edition. ++ #[inline] ++ pub fn try(&mut self, thing: F) -> Result ++ where ++ F: FnOnce(&mut Parser<'i, 't>) -> Result, ++ { ++ self.try_parse(thing) + } + + /// Execute the given closure, passing it the parser. +@@ -500,8 +516,10 @@ + /// the internal state of the parser (including position within the input) + /// is restored to what it was before the call. + #[inline] +- pub fn try(&mut self, thing: F) -> Result +- where F: FnOnce(&mut Parser<'i, 't>) -> Result { ++ pub fn try_parse(&mut self, thing: F) -> Result ++ where ++ F: FnOnce(&mut Parser<'i, 't>) -> Result, ++ { + let start = self.state(); + let result = thing(self); + if result.is_err() { +@@ -543,8 +561,8 @@ + loop { + match self.next_including_whitespace_and_comments() { + Err(e) => return Err(e), +- Ok(&Token::Comment(_)) => {}, +- _ => break ++ Ok(&Token::Comment(_)) => {} ++ _ => break, + } + } + Ok(self.input.cached_token_ref()) +@@ -556,39 +574,47 @@ + /// where comments are preserved. + /// When parsing higher-level values, per the CSS Syntax specification, + /// comments should always be ignored between tokens. +- pub fn next_including_whitespace_and_comments(&mut self) -> Result<&Token<'i>, BasicParseError<'i>> { ++ pub fn next_including_whitespace_and_comments( ++ &mut self, ++ ) -> Result<&Token<'i>, BasicParseError<'i>> { + if let Some(block_type) = self.at_start_of.take() { + consume_until_end_of_block(block_type, &mut self.input.tokenizer); + } + + let byte = self.input.tokenizer.next_byte(); + if self.stop_before.contains(Delimiters::from_byte(byte)) { +- return Err(self.new_basic_error(BasicParseErrorKind::EndOfInput)) ++ return Err(self.new_basic_error(BasicParseErrorKind::EndOfInput)); + } + + let token_start_position = self.input.tokenizer.position(); +- let token; +- match self.input.cached_token { +- Some(ref cached_token) +- if cached_token.start_position == token_start_position => { +- self.input.tokenizer.reset(&cached_token.end_state); +- match cached_token.token { +- Token::Function(ref name) => self.input.tokenizer.see_function(name), +- _ => {} +- } +- token = &cached_token.token ++ let using_cached_token = self ++ .input ++ .cached_token ++ .as_ref() ++ .map_or(false, |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); ++ match cached_token.token { ++ Token::Function(ref name) => self.input.tokenizer.see_function(name), ++ _ => {} + } +- _ => { +- let new_token = self.input.tokenizer.next() +- .map_err(|()| self.new_basic_error(BasicParseErrorKind::EndOfInput))?; +- self.input.cached_token = Some(CachedToken { +- token: new_token, +- start_position: token_start_position, +- end_state: self.input.tokenizer.state(), +- }); +- token = self.input.cached_token_ref() +- } +- } ++ &cached_token.token ++ } else { ++ let new_token = self ++ .input ++ .tokenizer ++ .next() ++ .map_err(|()| self.new_basic_error(BasicParseErrorKind::EndOfInput))?; ++ self.input.cached_token = Some(CachedToken { ++ token: new_token, ++ start_position: token_start_position, ++ end_state: self.input.tokenizer.state(), ++ }); ++ self.input.cached_token_ref() ++ }; + + if let Some(block_type) = BlockType::opening(token) { + self.at_start_of = Some(block_type); +@@ -602,7 +628,9 @@ + /// This can help tell e.g. `color: green;` from `color: green 4px;` + #[inline] + pub fn parse_entirely(&mut self, parse: F) -> Result> +- where F: FnOnce(&mut Parser<'i, 't>) -> Result> { ++ where ++ F: FnOnce(&mut Parser<'i, 't>) -> Result>, ++ { + let result = parse(self)?; + self.expect_exhausted()?; + Ok(result) +@@ -619,15 +647,20 @@ + /// This method retuns `Err(())` the first time that a closure call does, + /// or if a closure call leaves some input before the next comma or the end of the input. + #[inline] +- pub fn parse_comma_separated(&mut self, mut parse_one: F) -> Result, ParseError<'i, E>> +- where F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result> { ++ pub fn parse_comma_separated( ++ &mut self, ++ mut parse_one: F, ++ ) -> Result, ParseError<'i, E>> ++ where ++ F: for<'tt> FnMut(&mut Parser<'i, 'tt>) -> Result>, ++ { + // Vec grows from 0 to 4 by default on first push(). So allocate with + // capacity 1, so in the somewhat common case of only one item we don't + // way overallocate. Note that we always push at least one item if + // parsing succeeds. + let mut values = Vec::with_capacity(1); + loop { +- self.skip_whitespace(); // Unnecessary for correctness, but may help try() in parse_one rewind less. ++ self.skip_whitespace(); // Unnecessary for correctness, but may help try() in parse_one rewind less. + values.push(self.parse_until_before(Delimiter::Comma, &mut parse_one)?); + match self.next() { + Err(_) => return Ok(values), +@@ -649,8 +682,10 @@ + /// + /// The result is overridden to `Err(())` if the closure leaves some input before that point. + #[inline] +- pub fn parse_nested_block(&mut self, parse: F) -> Result > +- where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result> { ++ pub fn parse_nested_block(&mut self, parse: F) -> Result> ++ where ++ F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result>, ++ { + parse_nested_block(self, parse) + } + +@@ -663,9 +698,14 @@ + /// + /// The result is overridden to `Err(())` if the closure leaves some input before that point. + #[inline] +- pub fn parse_until_before(&mut self, delimiters: Delimiters, parse: F) +- -> Result > +- where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result> { ++ pub fn parse_until_before( ++ &mut self, ++ delimiters: Delimiters, ++ parse: F, ++ ) -> Result> ++ where ++ F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result>, ++ { + parse_until_before(self, delimiters, parse) + } + +@@ -675,9 +715,14 @@ + /// (e.g. if these is only one in the given set) + /// or if it was there at all (as opposed to reaching the end of the input). + #[inline] +- pub fn parse_until_after(&mut self, delimiters: Delimiters, parse: F) +- -> Result > +- where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result> { ++ pub fn parse_until_after( ++ &mut self, ++ delimiters: Delimiters, ++ parse: F, ++ ) -> Result> ++ where ++ F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result>, ++ { + parse_until_after(self, delimiters, parse) + } + +@@ -687,7 +732,7 @@ + let start_location = self.current_source_location(); + match *self.next_including_whitespace()? { + Token::WhiteSpace(value) => Ok(value), +- ref t => Err(start_location.new_basic_unexpected_token_error(t.clone())) ++ ref t => Err(start_location.new_basic_unexpected_token_error(t.clone())), + } + } + +@@ -707,7 +752,10 @@ + + /// Parse a whose unescaped value is an ASCII-insensitive match for the given value. + #[inline] +- pub fn expect_ident_matching(&mut self, expected_value: &str) -> Result<(), BasicParseError<'i>> { ++ pub fn expect_ident_matching( ++ &mut self, ++ expected_value: &str, ++ ) -> Result<(), BasicParseError<'i>> { + expect! {self, + Token::Ident(ref value) if value.eq_ignore_ascii_case(expected_value) => Ok(()), + } +@@ -744,8 +792,10 @@ + Token::UnquotedUrl(ref value) => return Ok(value.clone()), + Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {} + } +- self.parse_nested_block(|input| input.expect_string().map_err(Into::into).map(|s| s.clone())) +- .map_err(ParseError::<()>::basic) ++ self.parse_nested_block(|input| { ++ input.expect_string().map_err(Into::into).map(|s| s.clone()) ++ }) ++ .map_err(ParseError::<()>::basic) + } + + /// Parse either a or a , and return the unescaped value. +@@ -757,8 +807,10 @@ + Token::QuotedString(ref value) => return Ok(value.clone()), + Token::Function(ref name) if name.eq_ignore_ascii_case("url") => {} + } +- self.parse_nested_block(|input| input.expect_string().map_err(Into::into).map(|s| s.clone())) +- .map_err(ParseError::<()>::basic) ++ self.parse_nested_block(|input| { ++ input.expect_string().map_err(Into::into).map(|s| s.clone()) ++ }) ++ .map_err(ParseError::<()>::basic) + } + + /// Parse a and return the integer value. +@@ -862,7 +914,10 @@ + /// + /// If the result is `Ok`, you can then call the `Parser::parse_nested_block` method. + #[inline] +- pub fn expect_function_matching(&mut self, expected_name: &str) -> Result<(), BasicParseError<'i>> { ++ pub fn expect_function_matching( ++ &mut self, ++ expected_name: &str, ++ ) -> Result<(), BasicParseError<'i>> { + expect! {self, + Token::Function(ref name) if name.eq_ignore_ascii_case(expected_name) => Ok(()), + } +@@ -877,21 +932,22 @@ + let token; + loop { + match self.next_including_whitespace_and_comments() { +- Ok(&Token::Function(_)) | +- Ok(&Token::ParenthesisBlock) | +- Ok(&Token::SquareBracketBlock) | +- Ok(&Token::CurlyBracketBlock) => {} ++ Ok(&Token::Function(_)) ++ | Ok(&Token::ParenthesisBlock) ++ | Ok(&Token::SquareBracketBlock) ++ | Ok(&Token::CurlyBracketBlock) => {} + Ok(t) => { + if t.is_parse_error() { + token = t.clone(); +- break ++ break; + } +- continue ++ continue; + } +- Err(_) => return Ok(()) ++ Err(_) => return Ok(()), + } +- let result = self.parse_nested_block(|input| input.expect_no_error_token() +- .map_err(|e| Into::into(e))); ++ let result = self.parse_nested_block(|input| { ++ input.expect_no_error_token().map_err(|e| Into::into(e)) ++ }); + result.map_err(ParseError::<()>::basic)? + } + // FIXME: maybe these should be separate variants of BasicParseError instead? +@@ -899,11 +955,14 @@ + } + } + +-pub fn parse_until_before<'i: 't, 't, F, T, E>(parser: &mut Parser<'i, 't>, +- delimiters: Delimiters, +- parse: F) +- -> Result > +- where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result> { ++pub fn parse_until_before<'i: 't, 't, F, T, E>( ++ parser: &mut Parser<'i, 't>, ++ delimiters: Delimiters, ++ parse: F, ++) -> Result> ++where ++ F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result>, ++{ + let delimiters = parser.stop_before | delimiters; + let result; + // Introduce a new scope to limit duration of nested_parser’s borrow +@@ -921,27 +980,34 @@ + // FIXME: have a special-purpose tokenizer method for this that does less work. + loop { + if delimiters.contains(Delimiters::from_byte(parser.input.tokenizer.next_byte())) { +- break ++ break; + } + if let Ok(token) = parser.input.tokenizer.next() { + if let Some(block_type) = BlockType::opening(&token) { + consume_until_end_of_block(block_type, &mut parser.input.tokenizer); + } + } else { +- break ++ break; + } + } + result + } + +-pub fn parse_until_after<'i: 't, 't, F, T, E>(parser: &mut Parser<'i, 't>, +- delimiters: Delimiters, +- parse: F) +- -> Result > +- where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result> { ++pub fn parse_until_after<'i: 't, 't, F, T, E>( ++ parser: &mut Parser<'i, 't>, ++ delimiters: Delimiters, ++ parse: F, ++) -> Result> ++where ++ F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result>, ++{ + let result = parser.parse_until_before(delimiters, parse); + let next_byte = parser.input.tokenizer.next_byte(); +- if next_byte.is_some() && !parser.stop_before.contains(Delimiters::from_byte(next_byte)) { ++ if next_byte.is_some() ++ && !parser ++ .stop_before ++ .contains(Delimiters::from_byte(next_byte)) ++ { + debug_assert!(delimiters.contains(Delimiters::from_byte(next_byte))); + // We know this byte is ASCII. + parser.input.tokenizer.advance(1); +@@ -952,14 +1018,20 @@ + result + } + +-pub fn parse_nested_block<'i: 't, 't, F, T, E>(parser: &mut Parser<'i, 't>, parse: F) +- -> Result > +- where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result> { +- let block_type = parser.at_start_of.take().expect("\ +- A nested parser can only be created when a Function, \ +- ParenthesisBlock, SquareBracketBlock, or CurlyBracketBlock \ +- token was just consumed.\ +- "); ++pub fn parse_nested_block<'i: 't, 't, F, T, E>( ++ parser: &mut Parser<'i, 't>, ++ parse: F, ++) -> Result> ++where ++ F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result>, ++{ ++ let block_type = parser.at_start_of.take().expect( ++ "\ ++ A nested parser can only be created when a Function, \ ++ ParenthesisBlock, SquareBracketBlock, or CurlyBracketBlock \ ++ token was just consumed.\ ++ ", ++ ); + let closing_delimiter = match block_type { + BlockType::CurlyBracket => ClosingDelimiter::CloseCurlyBracket, + BlockType::SquareBracket => ClosingDelimiter::CloseSquareBracket, +diff --git a/third_party/rust/cssparser/src/rules_and_declarations.rs b/third_party/rust/cssparser/src/rules_and_declarations.rs +--- a/third_party/rust/cssparser/src/rules_and_declarations.rs ++++ b/third_party/rust/cssparser/src/rules_and_declarations.rs +@@ -4,15 +4,14 @@ + + // https://drafts.csswg.org/css-syntax/#parsing + +-use cow_rc_str::CowRcStr; +-use parser::{parse_until_before, parse_until_after, parse_nested_block, ParserState}; +-#[allow(unused_imports)] use std::ascii::AsciiExt; + use super::{BasicParseError, BasicParseErrorKind, Delimiter}; + use super::{ParseError, Parser, SourceLocation, Token}; ++use cow_rc_str::CowRcStr; ++use parser::{parse_nested_block, parse_until_after, parse_until_before, ParserState}; + + /// Parse `!important`. + /// +-/// Typical usage is `input.try(parse_important).is_ok()` ++/// Typical usage is `input.try_parse(parse_important).is_ok()` + /// at the end of a `DeclarationParser::parse_value` implementation. + pub fn parse_important<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), BasicParseError<'i>> { + input.expect_delim('!')?; +@@ -61,10 +60,13 @@ + /// (In declaration lists, before the next semicolon or end of the current block.) + /// + /// If `!important` can be used in a given context, +- /// `input.try(parse_important).is_ok()` should be used at the end ++ /// `input.try_parse(parse_important).is_ok()` should be used at the end + /// of the implementation of this method and the result should be part of the return value. +- fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) +- -> Result>; ++ fn parse_value<'t>( ++ &mut self, ++ name: CowRcStr<'i>, ++ input: &mut Parser<'i, 't>, ++ ) -> Result>; + } + + /// A trait to provide various parsing of at-rules. +@@ -106,9 +108,12 @@ + /// The given `input` is a "delimited" parser + /// that ends wherever the prelude should end. + /// (Before the next semicolon, the next `{`, or the end of the current block.) +- fn parse_prelude<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) +- -> Result, +- ParseError<'i, Self::Error>> { ++ fn parse_prelude<'t>( ++ &mut self, ++ name: CowRcStr<'i>, ++ input: &mut Parser<'i, 't>, ++ ) -> Result, ParseError<'i, Self::Error>> ++ { + let _ = name; + let _ = input; + Err(input.new_error(BasicParseErrorKind::AtRuleInvalid(name))) +@@ -129,8 +134,10 @@ + ) -> Self::AtRule { + let _ = prelude; + let _ = location; +- panic!("The `AtRuleParser::rule_without_block` method must be overriden \ +- if `AtRuleParser::parse_prelude` ever returns `AtRuleType::WithoutBlock`.") ++ panic!( ++ "The `AtRuleParser::rule_without_block` method must be overriden \ ++ if `AtRuleParser::parse_prelude` ever returns `AtRuleType::WithoutBlock`." ++ ) + } + + /// Parse the content of a `{ /* ... */ }` block for the body of the at-rule. +@@ -185,8 +192,10 @@ + /// + /// The given `input` is a "delimited" parser + /// that ends where the prelude should end (before the next `{`). +- fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) +- -> Result> { ++ fn parse_prelude<'t>( ++ &mut self, ++ input: &mut Parser<'i, 't>, ++ ) -> Result> { + let _ = input; + Err(input.new_error(BasicParseErrorKind::QualifiedRuleInvalid)) + } +@@ -211,7 +220,6 @@ + } + } + +- + /// Provides an iterator for declaration list parsing. + pub struct DeclarationListParser<'i: 't, 't: 'a, 'a, P> { + /// The input given to `DeclarationListParser::new` +@@ -221,10 +229,10 @@ + pub parser: P, + } + +- + impl<'i: 't, 't: 'a, 'a, I, P, E: 'i> DeclarationListParser<'i, 't, 'a, P> +-where P: DeclarationParser<'i, Declaration = I, Error = E> + +- AtRuleParser<'i, AtRule = I, Error = E> { ++where ++ P: DeclarationParser<'i, Declaration = I, Error = E> + AtRuleParser<'i, AtRule = I, Error = E>, ++{ + /// Create a new `DeclarationListParser` for the given `input` and `parser`. + /// + /// Note that all CSS declaration lists can on principle contain at-rules. +@@ -250,8 +258,9 @@ + /// `DeclarationListParser` is an iterator that yields `Ok(_)` for a valid declaration or at-rule + /// or `Err(())` for an invalid one. + impl<'i: 't, 't: 'a, 'a, I, P, E: 'i> Iterator for DeclarationListParser<'i, 't, 'a, P> +-where P: DeclarationParser<'i, Declaration = I, Error = E> + +- AtRuleParser<'i, AtRule = I, Error = E> { ++where ++ P: DeclarationParser<'i, Declaration = I, Error = E> + AtRuleParser<'i, AtRule = I, Error = E>, ++{ + type Item = Result, &'i str)>; + + fn next(&mut self) -> Option { +@@ -259,7 +268,9 @@ + let start = self.input.state(); + // FIXME: remove intermediate variable when lifetimes are non-lexical + let ident = match self.input.next_including_whitespace_and_comments() { +- Ok(&Token::WhiteSpace(_)) | Ok(&Token::Comment(_)) | Ok(&Token::Semicolon) => continue, ++ Ok(&Token::WhiteSpace(_)) | Ok(&Token::Comment(_)) | Ok(&Token::Semicolon) => { ++ continue ++ } + Ok(&Token::Ident(ref name)) => Ok(Ok(name.clone())), + Ok(&Token::AtKeyword(ref name)) => Ok(Err(name.clone())), + Ok(token) => Err(token.clone()), +@@ -271,28 +282,33 @@ + let result = { + let parser = &mut self.parser; + // FIXME: https://github.com/rust-lang/rust/issues/42508 +- parse_until_after::<'i, 't, _, _, _>(self.input, Delimiter::Semicolon, |input| { +- input.expect_colon()?; +- parser.parse_value(name, input) +- }) ++ parse_until_after::<'i, 't, _, _, _>( ++ self.input, ++ Delimiter::Semicolon, ++ |input| { ++ input.expect_colon()?; ++ parser.parse_value(name, input) ++ }, ++ ) + }; +- return Some(result.map_err(|e| (e, self.input.slice_from(start.position())))) ++ return Some(result.map_err(|e| (e, self.input.slice_from(start.position())))); + } + Ok(Err(name)) => { + // At-keyword +- return Some(parse_at_rule(&start, name, self.input, &mut self.parser)) ++ return Some(parse_at_rule(&start, name, self.input, &mut self.parser)); + } + Err(token) => { + let result = self.input.parse_until_after(Delimiter::Semicolon, |_| { +- Err(start.source_location().new_unexpected_token_error(token.clone())) ++ Err(start ++ .source_location() ++ .new_unexpected_token_error(token.clone())) + }); +- return Some(result.map_err(|e| (e, self.input.slice_from(start.position())))) +- } +- } +- } +- } +-} +- ++ return Some(result.map_err(|e| (e, self.input.slice_from(start.position())))); ++ } ++ } ++ } ++ } ++} + + /// Provides an iterator for rule list parsing. + pub struct RuleListParser<'i: 't, 't: 'a, 'a, P> { +@@ -306,10 +322,11 @@ + any_rule_so_far: bool, + } + +- + impl<'i: 't, 't: 'a, 'a, R, P, E: 'i> RuleListParser<'i, 't, 'a, P> +-where P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> + +- AtRuleParser<'i, AtRule = R, Error = E> { ++where ++ P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> ++ + AtRuleParser<'i, AtRule = R, Error = E>, ++{ + /// Create a new `RuleListParser` for the given `input` at the top-level of a stylesheet + /// and the given `parser`. + /// +@@ -345,12 +362,12 @@ + } + } + +- +- + /// `RuleListParser` is an iterator that yields `Ok(_)` for a rule or `Err(())` for an invalid one. + impl<'i: 't, 't: 'a, 'a, R, P, E: 'i> Iterator for RuleListParser<'i, 't, 'a, P> +-where P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> + +- AtRuleParser<'i, AtRule = R, Error = E> { ++where ++ P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> ++ + AtRuleParser<'i, AtRule = R, Error = E>, ++{ + type Item = Result, &'i str)>; + + fn next(&mut self) -> Option { +@@ -375,7 +392,7 @@ + } + } + Some(_) => at_keyword = None, +- None => return None ++ None => return None, + } + + if let Some(name) = at_keyword { +@@ -383,40 +400,52 @@ + self.any_rule_so_far = true; + if first_stylesheet_rule && name.eq_ignore_ascii_case("charset") { + let delimiters = Delimiter::Semicolon | Delimiter::CurlyBracketBlock; +- let _: Result<(), ParseError<()>> = self.input.parse_until_after(delimiters, |_| Ok(())); ++ let _: Result<(), ParseError<()>> = ++ self.input.parse_until_after(delimiters, |_| Ok(())); + } else { +- return Some(parse_at_rule(&start, name.clone(), self.input, &mut self.parser)) ++ return Some(parse_at_rule( ++ &start, ++ name.clone(), ++ self.input, ++ &mut self.parser, ++ )); + } + } else { + self.any_rule_so_far = true; + let result = parse_qualified_rule(self.input, &mut self.parser); +- return Some(result.map_err(|e| (e, self.input.slice_from(start.position())))) +- } +- } +- } +-} +- ++ return Some(result.map_err(|e| (e, self.input.slice_from(start.position())))); ++ } ++ } ++ } ++} + + /// Parse a single declaration, such as an `( /* ... */ )` parenthesis in an `@supports` prelude. +-pub fn parse_one_declaration<'i, 't, P, E>(input: &mut Parser<'i, 't>, parser: &mut P) +- -> Result<

>::Declaration, +- (ParseError<'i, E>, &'i str)> +- where P: DeclarationParser<'i, Error = E> { ++pub fn parse_one_declaration<'i, 't, P, E>( ++ input: &mut Parser<'i, 't>, ++ parser: &mut P, ++) -> Result<

>::Declaration, (ParseError<'i, E>, &'i str)> ++where ++ P: DeclarationParser<'i, Error = E>, ++{ + let start_position = input.position(); +- input.parse_entirely(|input| { +- let name = input.expect_ident()?.clone(); +- input.expect_colon()?; +- parser.parse_value(name, input) +- }) +- .map_err(|e| (e, input.slice_from(start_position))) +-} +- ++ input ++ .parse_entirely(|input| { ++ let name = input.expect_ident()?.clone(); ++ input.expect_colon()?; ++ parser.parse_value(name, input) ++ }) ++ .map_err(|e| (e, input.slice_from(start_position))) ++} + + /// Parse a single rule, such as for CSSOM’s `CSSStyleSheet.insertRule`. +-pub fn parse_one_rule<'i, 't, R, P, E>(input: &mut Parser<'i, 't>, parser: &mut P) +- -> Result> +-where P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> + +- AtRuleParser<'i, AtRule = R, Error = E> { ++pub fn parse_one_rule<'i, 't, R, P, E>( ++ input: &mut Parser<'i, 't>, ++ parser: &mut P, ++) -> Result> ++where ++ P: QualifiedRuleParser<'i, QualifiedRule = R, Error = E> ++ + AtRuleParser<'i, AtRule = R, Error = E>, ++{ + input.parse_entirely(|input| { + input.skip_whitespace(); + let start = input.state(); +@@ -450,7 +479,7 @@ + parser: &mut P, + ) -> Result<

>::AtRule, (ParseError<'i, E>, &'i str)> + where +- P: AtRuleParser<'i, Error = E> ++ P: AtRuleParser<'i, Error = E>, + { + let location = input.current_source_location(); + let delimiters = Delimiter::Semicolon | Delimiter::CurlyBracketBlock; +@@ -459,67 +488,64 @@ + parser.parse_prelude(name, input) + }); + match result { +- Ok(AtRuleType::WithoutBlock(prelude)) => { +- match input.next() { +- Ok(&Token::Semicolon) | Err(_) => Ok(parser.rule_without_block(prelude, location)), +- Ok(&Token::CurlyBracketBlock) => Err(( +- input.new_unexpected_token_error(Token::CurlyBracketBlock), +- input.slice_from(start.position()), +- )), +- Ok(_) => unreachable!() +- } +- } ++ Ok(AtRuleType::WithoutBlock(prelude)) => match input.next() { ++ Ok(&Token::Semicolon) | Err(_) => Ok(parser.rule_without_block(prelude, location)), ++ Ok(&Token::CurlyBracketBlock) => Err(( ++ input.new_unexpected_token_error(Token::CurlyBracketBlock), ++ input.slice_from(start.position()), ++ )), ++ Ok(_) => unreachable!(), ++ }, + Ok(AtRuleType::WithBlock(prelude)) => { + match input.next() { + Ok(&Token::CurlyBracketBlock) => { + // FIXME: https://github.com/rust-lang/rust/issues/42508 +- parse_nested_block::<'i, 't, _, _, _>( +- input, +- move |input| parser.parse_block(prelude, location, input) +- ).map_err(|e| (e, input.slice_from(start.position()))) ++ parse_nested_block::<'i, 't, _, _, _>(input, move |input| { ++ parser.parse_block(prelude, location, input) ++ }) ++ .map_err(|e| (e, input.slice_from(start.position()))) + } + Ok(&Token::Semicolon) => Err(( + input.new_unexpected_token_error(Token::Semicolon), + input.slice_from(start.position()), + )), + Err(e) => Err((e.into(), input.slice_from(start.position()))), +- Ok(_) => unreachable!() ++ Ok(_) => unreachable!(), + } + } + Err(error) => { + let end_position = input.position(); + match input.next() { +- Ok(&Token::CurlyBracketBlock) | Ok(&Token::Semicolon) | Err(_) => {}, +- _ => unreachable!() ++ Ok(&Token::CurlyBracketBlock) | Ok(&Token::Semicolon) | Err(_) => {} ++ _ => unreachable!(), + }; + Err((error, input.slice(start.position()..end_position))) + } + } + } +- + + fn parse_qualified_rule<'i, 't, P, E>( + input: &mut Parser<'i, 't>, + parser: &mut P, + ) -> Result<

>::QualifiedRule, ParseError<'i, E>> + where +- P: QualifiedRuleParser<'i, Error = E> ++ P: QualifiedRuleParser<'i, Error = E>, + { + let location = input.current_source_location(); + // FIXME: https://github.com/rust-lang/rust/issues/42508 +- let prelude = parse_until_before::<'i, 't, _, _, _>(input, Delimiter::CurlyBracketBlock, |input| { +- parser.parse_prelude(input) +- }); ++ let prelude = ++ parse_until_before::<'i, 't, _, _, _>(input, Delimiter::CurlyBracketBlock, |input| { ++ parser.parse_prelude(input) ++ }); + match *input.next()? { + Token::CurlyBracketBlock => { + // Do this here so that we consume the `{` even if the prelude is `Err`. + let prelude = prelude?; + // FIXME: https://github.com/rust-lang/rust/issues/42508 +- parse_nested_block::<'i, 't, _, _, _>( +- input, +- move |input| parser.parse_block(prelude, location, input), +- ) +- } +- _ => unreachable!() +- } +-} ++ parse_nested_block::<'i, 't, _, _, _>(input, move |input| { ++ parser.parse_block(prelude, location, input) ++ }) ++ } ++ _ => unreachable!(), ++ } ++} +diff --git a/third_party/rust/cssparser/src/serializer.rs b/third_party/rust/cssparser/src/serializer.rs +--- a/third_party/rust/cssparser/src/serializer.rs ++++ b/third_party/rust/cssparser/src/serializer.rs +@@ -4,18 +4,18 @@ + + use dtoa_short::{self, Notation}; + use itoa; +-#[allow(unused_imports)] use std::ascii::AsciiExt; + use std::fmt::{self, Write}; + use std::io; + use std::str; + + use super::Token; + +- + /// Trait for things the can serialize themselves in CSS syntax. + pub trait ToCss { + /// Serialize `self` in CSS syntax, writing to `dest`. +- fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write; ++ fn to_css(&self, dest: &mut W) -> fmt::Result ++ where ++ W: fmt::Write; + + /// Serialize `self` in CSS syntax and return a string. + /// +@@ -29,8 +29,10 @@ + } + + #[inline] +-fn write_numeric(value: f32, int_value: Option, has_sign: bool, dest: &mut W) +- -> fmt::Result where W: fmt::Write { ++fn write_numeric(value: f32, int_value: Option, has_sign: bool, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + // `value.value >= 0` is true for negative 0. + if has_sign && value.is_sign_positive() { + dest.write_str("+")?; +@@ -39,7 +41,10 @@ + 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 } ++ Notation { ++ decimal_point: false, ++ scientific: false, ++ } + } else { + dtoa_short::write(dest, value)? + }; +@@ -52,19 +57,21 @@ + Ok(()) + } + +- + impl<'a> ToCss for Token<'a> { +- fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { ++ fn to_css(&self, dest: &mut W) -> fmt::Result ++ where ++ W: fmt::Write, ++ { + match *self { + Token::Ident(ref value) => serialize_identifier(&**value, dest)?, + Token::AtKeyword(ref value) => { + dest.write_str("@")?; + serialize_identifier(&**value, dest)?; +- }, ++ } + Token::Hash(ref value) => { + dest.write_str("#")?; + serialize_name(value, dest)?; +- }, ++ } + Token::IDHash(ref value) => { + dest.write_str("#")?; + serialize_identifier(&**value, dest)?; +@@ -74,17 +81,28 @@ + dest.write_str("url(")?; + serialize_unquoted_url(&**value, dest)?; + dest.write_str(")")?; +- }, ++ } + Token::Delim(value) => dest.write_char(value)?, + +- Token::Number { value, int_value, has_sign } => { +- write_numeric(value, int_value, has_sign, dest)? +- } +- Token::Percentage { unit_value, int_value, has_sign } => { ++ Token::Number { ++ value, ++ int_value, ++ has_sign, ++ } => write_numeric(value, int_value, has_sign, dest)?, ++ Token::Percentage { ++ unit_value, ++ int_value, ++ has_sign, ++ } => { + write_numeric(unit_value * 100., int_value, has_sign, dest)?; + dest.write_str("%")?; +- }, +- Token::Dimension { value, int_value, has_sign, ref unit } => { ++ } ++ Token::Dimension { ++ value, ++ int_value, ++ has_sign, ++ ref unit, ++ } => { + write_numeric(value, int_value, has_sign, dest)?; + // Disambiguate with scientific notation. + let unit = &**unit; +@@ -94,7 +112,7 @@ + } else { + serialize_identifier(unit, dest)?; + } +- }, ++ } + + Token::WhiteSpace(content) => dest.write_str(content)?, + Token::Comment(content) => { +@@ -116,7 +134,7 @@ + Token::Function(ref name) => { + serialize_identifier(&**name, dest)?; + dest.write_str("(")?; +- }, ++ } + Token::ParenthesisBlock => dest.write_str("(")?, + Token::SquareBracketBlock => dest.write_str("[")?, + Token::CurlyBracketBlock => dest.write_str("{")?, +@@ -134,7 +152,7 @@ + // and therefore does not have a closing quote. + dest.write_char('"')?; + CssStringWriter::new(dest).write_str(value)?; +- }, ++ } + Token::CloseParenthesis => dest.write_str(")")?, + Token::CloseSquareBracket => dest.write_str("]")?, + Token::CloseCurlyBracket => dest.write_str("}")?, +@@ -143,7 +161,10 @@ + } + } + +-fn hex_escape(ascii_byte: u8, dest: &mut W) -> fmt::Result where W:fmt::Write { ++fn hex_escape(ascii_byte: u8, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + static HEX_DIGITS: &'static [u8; 16] = b"0123456789abcdef"; + let b3; + let b4; +@@ -159,15 +180,21 @@ + dest.write_str(unsafe { str::from_utf8_unchecked(&bytes) }) + } + +-fn char_escape(ascii_byte: u8, dest: &mut W) -> fmt::Result where W:fmt::Write { ++fn char_escape(ascii_byte: u8, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + let bytes = [b'\\', ascii_byte]; + dest.write_str(unsafe { str::from_utf8_unchecked(&bytes) }) + } + + /// Write a CSS identifier, escaping characters as necessary. +-pub fn serialize_identifier(mut value: &str, dest: &mut W) -> fmt::Result where W:fmt::Write { ++pub fn serialize_identifier(mut value: &str, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + if value.is_empty() { +- return Ok(()) ++ return Ok(()); + } + + if value.starts_with("--") { +@@ -192,7 +219,10 @@ + /// + /// You should only use this when you know what you're doing, when in doubt, + /// consider using `serialize_identifier`. +-pub fn serialize_name(value: &str, dest: &mut W) -> fmt::Result where W:fmt::Write { ++pub fn serialize_name(value: &str, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + let mut chunk_start = 0; + for (i, b) in value.bytes().enumerate() { + let escaped = match b { +@@ -214,14 +244,16 @@ + dest.write_str(&value[chunk_start..]) + } + +- +-fn serialize_unquoted_url(value: &str, dest: &mut W) -> fmt::Result where W:fmt::Write { ++fn serialize_unquoted_url(value: &str, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + let mut chunk_start = 0; + for (i, b) in value.bytes().enumerate() { + let hex = match b { +- b'\0' ... b' ' | b'\x7F' => true, ++ b'\0'...b' ' | b'\x7F' => true, + b'(' | b')' | b'"' | b'\'' | b'\\' => false, +- _ => continue ++ _ => continue, + }; + dest.write_str(&value[chunk_start..i])?; + if hex { +@@ -234,15 +266,16 @@ + dest.write_str(&value[chunk_start..]) + } + +- + /// Write a double-quoted CSS string token, escaping content as necessary. +-pub fn serialize_string(value: &str, dest: &mut W) -> fmt::Result where W: fmt::Write { ++pub fn serialize_string(value: &str, dest: &mut W) -> fmt::Result ++where ++ W: fmt::Write, ++{ + dest.write_str("\"")?; + CssStringWriter::new(dest).write_str(value)?; + dest.write_str("\"")?; + Ok(()) + } +- + + /// A `fmt::Write` adapter that escapes text for writing as a double-quoted CSS string. + /// Quotes are not included. +@@ -251,12 +284,12 @@ + /// + /// ```{rust,ignore} + /// fn write_foo(foo: &Foo, dest: &mut W) -> fmt::Result where W: fmt::Write { +-/// try!(dest.write_str("\"")); ++/// dest.write_str("\"")?; + /// { + /// let mut string_dest = CssStringWriter::new(dest); + /// // Write into string_dest... + /// } +-/// try!(dest.write_str("\"")); ++/// dest.write_str("\"")?; + /// Ok(()) + /// } + /// ``` +@@ -264,14 +297,20 @@ + inner: &'a mut W, + } + +-impl<'a, W> CssStringWriter<'a, W> where W: fmt::Write { ++impl<'a, W> CssStringWriter<'a, W> ++where ++ W: fmt::Write, ++{ + /// Wrap a text writer to create a `CssStringWriter`. + pub fn new(inner: &'a mut W) -> CssStringWriter<'a, W> { + CssStringWriter { inner: inner } + } + } + +-impl<'a, W> fmt::Write for CssStringWriter<'a, W> where W: fmt::Write { ++impl<'a, W> fmt::Write for CssStringWriter<'a, W> ++where ++ W: fmt::Write, ++{ + fn write_str(&mut self, s: &str) -> fmt::Result { + let mut chunk_start = 0; + for (i, b) in s.bytes().enumerate() { +@@ -293,11 +332,13 @@ + } + } + +- + macro_rules! impl_tocss_for_int { + ($T: ty) => { + impl<'a> ToCss for $T { +- fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { ++ fn to_css(&self, dest: &mut W) -> fmt::Result ++ where ++ W: fmt::Write, ++ { + struct AssumeUtf8(W); + + impl io::Write for AssumeUtf8 { +@@ -305,7 +346,8 @@ + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + // Safety: itoa only emits ASCII, which is also well-formed UTF-8. + debug_assert!(buf.is_ascii()); +- self.0.write_str(unsafe { str::from_utf8_unchecked(buf) }) ++ self.0 ++ .write_str(unsafe { str::from_utf8_unchecked(buf) }) + .map_err(|_| io::ErrorKind::Other.into()) + } + +@@ -323,11 +365,11 @@ + + match itoa::write(AssumeUtf8(dest), *self) { + Ok(_) => Ok(()), +- Err(_) => Err(fmt::Error) ++ Err(_) => Err(fmt::Error), + } + } + } +- } ++ }; + } + + impl_tocss_for_int!(i8); +@@ -342,11 +384,14 @@ + macro_rules! impl_tocss_for_float { + ($T: ty) => { + impl<'a> ToCss for $T { +- fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { ++ fn to_css(&self, dest: &mut W) -> fmt::Result ++ where ++ W: fmt::Write, ++ { + dtoa_short::write(dest, *self).map(|_| ()) + } + } +- } ++ }; + } + + impl_tocss_for_float!(f32); +@@ -381,22 +426,33 @@ + pub fn needs_separator_when_before(self, other: TokenSerializationType) -> bool { + use self::TokenSerializationTypeVariants::*; + match self.0 { +- Ident => matches!(other.0, +- Ident | Function | UrlOrBadUrl | DelimMinus | Number | Percentage | Dimension | +- CDC | OpenParen), +- AtKeywordOrHash | Dimension => matches!(other.0, +- Ident | Function | UrlOrBadUrl | DelimMinus | Number | Percentage | Dimension | +- CDC), +- DelimHash | DelimMinus | Number => matches!(other.0, +- Ident | Function | UrlOrBadUrl | DelimMinus | Number | Percentage | Dimension), +- DelimAt => matches!(other.0, +- Ident | Function | UrlOrBadUrl | DelimMinus), ++ Ident => matches!( ++ other.0, ++ Ident ++ | Function ++ | UrlOrBadUrl ++ | DelimMinus ++ | Number ++ | Percentage ++ | Dimension ++ | CDC ++ | OpenParen ++ ), ++ AtKeywordOrHash | Dimension => matches!( ++ other.0, ++ Ident | Function | UrlOrBadUrl | DelimMinus | Number | Percentage | Dimension | CDC ++ ), ++ DelimHash | DelimMinus | Number => matches!( ++ other.0, ++ Ident | Function | UrlOrBadUrl | DelimMinus | Number | Percentage | Dimension ++ ), ++ DelimAt => matches!(other.0, Ident | Function | UrlOrBadUrl | DelimMinus), + DelimDotOrPlus => matches!(other.0, Number | Percentage | Dimension), + DelimAssorted | DelimAsterisk => matches!(other.0, DelimEquals), + DelimBar => matches!(other.0, DelimEquals | DelimBar | DashMatch), + DelimSlash => matches!(other.0, DelimAsterisk | SubstringMatch), +- Nothing | WhiteSpace | Percentage | UrlOrBadUrl | Function | CDC | OpenParen | +- DashMatch | SubstringMatch | DelimQuestion | DelimEquals | Other => false, ++ Nothing | WhiteSpace | Percentage | UrlOrBadUrl | Function | CDC | OpenParen ++ | DashMatch | SubstringMatch | DelimQuestion | DelimEquals | Other => false, + } + } + } +@@ -415,18 +471,18 @@ + CDC, + DashMatch, + SubstringMatch, +- OpenParen, // '(' +- DelimHash, // '#' +- DelimAt, // '@' +- DelimDotOrPlus, // '.', '+' +- DelimMinus, // '-' +- DelimQuestion, // '?' +- DelimAssorted, // '$', '^', '~' +- DelimEquals, // '=' +- DelimBar, // '|' +- DelimSlash, // '/' +- DelimAsterisk, // '*' +- Other, // anything else ++ OpenParen, // '(' ++ DelimHash, // '#' ++ DelimAt, // '@' ++ DelimDotOrPlus, // '.', '+' ++ DelimMinus, // '-' ++ DelimQuestion, // '?' ++ DelimAssorted, // '$', '^', '~' ++ DelimEquals, // '=' ++ DelimBar, // '|' ++ DelimSlash, // '/' ++ DelimAsterisk, // '*' ++ Other, // anything else + } + + impl<'a> Token<'a> { +@@ -460,12 +516,21 @@ + Token::CDC => CDC, + Token::Function(_) => Function, + Token::ParenthesisBlock => OpenParen, +- Token::SquareBracketBlock | Token::CurlyBracketBlock | +- Token::CloseParenthesis | Token::CloseSquareBracket | Token::CloseCurlyBracket | +- Token::QuotedString(_) | Token::BadString(_) | +- Token::Delim(_) | Token::Colon | Token::Semicolon | Token::Comma | Token::CDO | +- Token::IncludeMatch | Token::PrefixMatch | Token::SuffixMatch +- => Other, ++ Token::SquareBracketBlock ++ | Token::CurlyBracketBlock ++ | Token::CloseParenthesis ++ | Token::CloseSquareBracket ++ | Token::CloseCurlyBracket ++ | Token::QuotedString(_) ++ | Token::BadString(_) ++ | Token::Delim(_) ++ | Token::Colon ++ | Token::Semicolon ++ | Token::Comma ++ | Token::CDO ++ | Token::IncludeMatch ++ | Token::PrefixMatch ++ | Token::SuffixMatch => Other, + }) + } + } +diff --git a/third_party/rust/cssparser/src/size_of_tests.rs b/third_party/rust/cssparser/src/size_of_tests.rs +--- a/third_party/rust/cssparser/src/size_of_tests.rs ++++ b/third_party/rust/cssparser/src/size_of_tests.rs +@@ -16,18 +16,24 @@ + panic!( + "Your changes have decreased the stack size of {} from {} to {}. \ + Good work! Please update the expected size in {}.", +- stringify!($t), old, new, file!() ++ stringify!($t), ++ old, ++ new, ++ file!() + ) + } else if new > old { + panic!( + "Your changes have increased the stack size of {} from {} to {}. \ + Please consider choosing a design which avoids this increase. \ + If you feel that the increase is necessary, update the size in {}.", +- stringify!($t), old, new, file!() ++ stringify!($t), ++ old, ++ new, ++ file!() + ) + } + } +- } ++ }; + } + + // Some of these assume 64-bit +@@ -36,10 +42,18 @@ + size_of_test!(cow_rc_str, CowRcStr, 16); + + size_of_test!(tokenizer, ::tokenizer::Tokenizer, 72); +-size_of_test!(parser_input, ::parser::ParserInput, if cfg!(rustc_has_pr45225) { 136 } else { 144 }); ++size_of_test!( ++ parser_input, ++ ::parser::ParserInput, ++ if cfg!(rustc_has_pr45225) { 136 } else { 144 } ++); + size_of_test!(parser, ::parser::Parser, 16); + size_of_test!(source_position, ::SourcePosition, 8); + size_of_test!(parser_state, ::ParserState, 24); + + size_of_test!(basic_parse_error, ::BasicParseError, 48); +-size_of_test!(parse_error_lower_bound, ::ParseError<()>, if cfg!(rustc_has_pr45225) { 48 } else { 56 }); ++size_of_test!( ++ parse_error_lower_bound, ++ ::ParseError<()>, ++ if cfg!(rustc_has_pr45225) { 48 } else { 56 } ++); +diff --git a/third_party/rust/cssparser/src/tests.rs b/third_party/rust/cssparser/src/tests.rs +--- a/third_party/rust/cssparser/src/tests.rs ++++ b/third_party/rust/cssparser/src/tests.rs +@@ -11,14 +11,13 @@ + #[cfg(feature = "bench")] + use self::test::Bencher; + +-use super::{Parser, Delimiter, Token, SourceLocation, +- ParseError, ParseErrorKind, BasicParseError, BasicParseErrorKind, +- DeclarationListParser, DeclarationParser, RuleListParser, +- AtRuleType, AtRuleParser, QualifiedRuleParser, ParserInput, +- parse_one_declaration, parse_one_rule, parse_important, +- stylesheet_encoding, EncodingSupport, +- TokenSerializationType, CowRcStr, +- Color, RGBA, parse_nth, UnicodeRange, ToCss}; ++use super::{ ++ parse_important, parse_nth, parse_one_declaration, parse_one_rule, stylesheet_encoding, ++ AtRuleParser, AtRuleType, BasicParseError, BasicParseErrorKind, Color, CowRcStr, ++ DeclarationListParser, DeclarationParser, Delimiter, EncodingSupport, ParseError, ++ ParseErrorKind, Parser, ParserInput, QualifiedRuleParser, RuleListParser, SourceLocation, ++ ToCss, Token, TokenSerializationType, UnicodeRange, RGBA, ++}; + + macro_rules! JArray { + ($($e: expr,)*) => { JArray![ $( $e ),* ] }; +@@ -37,9 +36,11 @@ + (&Json::Boolean(a), &Json::Boolean(b)) => a == b, + (&Json::String(ref a), &Json::String(ref b)) => a == b, + (&Json::Array(ref a), &Json::Array(ref b)) => { +- a.len() == b.len() && +- a.iter().zip(b.iter()).all(|(ref a, ref b)| almost_equals(*a, *b)) +- }, ++ a.len() == b.len() ++ && a.iter() ++ .zip(b.iter()) ++ .all(|(ref a, ref b)| almost_equals(*a, *b)) ++ } + (&Json::Object(_), &Json::Object(_)) => panic!("Not implemented"), + (&Json::Null, &Json::Null) => true, + _ => false, +@@ -65,11 +66,14 @@ + fn assert_json_eq(results: json::Json, mut expected: json::Json, message: &str) { + normalize(&mut expected); + if !almost_equals(&results, &expected) { +- println!("{}", ::difference::Changeset::new( +- &results.pretty().to_string(), +- &expected.pretty().to_string(), +- "\n", +- )); ++ println!( ++ "{}", ++ ::difference::Changeset::new( ++ &results.pretty().to_string(), ++ &expected.pretty().to_string(), ++ "\n", ++ ) ++ ); + panic!("{}", message) + } + } +@@ -77,7 +81,7 @@ + fn run_raw_json_tests ()>(json_data: &str, run: F) { + let items = match Json::from_str(json_data) { + Ok(Json::Array(items)) => items, +- _ => panic!("Invalid JSON") ++ _ => panic!("Invalid JSON"), + }; + assert!(items.len() % 2 == 0); + let mut input = None; +@@ -87,82 +91,88 @@ + (&Some(_), expected) => { + let input = input.take().unwrap(); + run(input, expected) +- }, ++ } + }; + } + } + +- + fn run_json_tests Json>(json_data: &str, parse: F) { +- run_raw_json_tests(json_data, |input, expected| { +- match input { +- Json::String(input) => { +- let mut parse_input = ParserInput::new(&input); +- let result = parse(&mut Parser::new(&mut parse_input)); +- assert_json_eq(result, expected, &input); +- }, +- _ => panic!("Unexpected JSON") +- } ++ run_raw_json_tests(json_data, |input, expected| match input { ++ Json::String(input) => { ++ let mut parse_input = ParserInput::new(&input); ++ let result = parse(&mut Parser::new(&mut parse_input)); ++ assert_json_eq(result, expected, &input); ++ } ++ _ => panic!("Unexpected JSON"), + }); + } + +- + #[test] + fn component_value_list() { +- run_json_tests(include_str!("css-parsing-tests/component_value_list.json"), |input| { +- Json::Array(component_values_to_json(input)) +- }); +-} +- ++ run_json_tests( ++ include_str!("css-parsing-tests/component_value_list.json"), ++ |input| Json::Array(component_values_to_json(input)), ++ ); ++} + + #[test] + fn one_component_value() { +- run_json_tests(include_str!("css-parsing-tests/one_component_value.json"), |input| { +- let result: Result> = input.parse_entirely(|input| { +- Ok(one_component_value_to_json(input.next()?.clone(), input)) +- }); +- result.unwrap_or(JArray!["error", "invalid"]) +- }); +-} +- ++ run_json_tests( ++ include_str!("css-parsing-tests/one_component_value.json"), ++ |input| { ++ let result: Result> = input.parse_entirely(|input| { ++ Ok(one_component_value_to_json(input.next()?.clone(), input)) ++ }); ++ result.unwrap_or(JArray!["error", "invalid"]) ++ }, ++ ); ++} + + #[test] + fn declaration_list() { +- run_json_tests(include_str!("css-parsing-tests/declaration_list.json"), |input| { +- Json::Array(DeclarationListParser::new(input, JsonParser).map(|result| { +- result.unwrap_or(JArray!["error", "invalid"]) +- }).collect()) +- }); +-} +- ++ run_json_tests( ++ include_str!("css-parsing-tests/declaration_list.json"), ++ |input| { ++ Json::Array( ++ DeclarationListParser::new(input, JsonParser) ++ .map(|result| result.unwrap_or(JArray!["error", "invalid"])) ++ .collect(), ++ ) ++ }, ++ ); ++} + + #[test] + fn one_declaration() { +- run_json_tests(include_str!("css-parsing-tests/one_declaration.json"), |input| { +- parse_one_declaration(input, &mut JsonParser).unwrap_or(JArray!["error", "invalid"]) +- }); +-} +- ++ run_json_tests( ++ include_str!("css-parsing-tests/one_declaration.json"), ++ |input| { ++ parse_one_declaration(input, &mut JsonParser).unwrap_or(JArray!["error", "invalid"]) ++ }, ++ ); ++} + + #[test] + fn rule_list() { + run_json_tests(include_str!("css-parsing-tests/rule_list.json"), |input| { +- Json::Array(RuleListParser::new_for_nested_rule(input, JsonParser).map(|result| { +- result.unwrap_or(JArray!["error", "invalid"]) +- }).collect()) ++ Json::Array( ++ RuleListParser::new_for_nested_rule(input, JsonParser) ++ .map(|result| result.unwrap_or(JArray!["error", "invalid"])) ++ .collect(), ++ ) + }); + } +- + + #[test] + fn stylesheet() { + run_json_tests(include_str!("css-parsing-tests/stylesheet.json"), |input| { +- Json::Array(RuleListParser::new_for_stylesheet(input, JsonParser).map(|result| { +- result.unwrap_or(JArray!["error", "invalid"]) +- }).collect()) ++ Json::Array( ++ RuleListParser::new_for_stylesheet(input, JsonParser) ++ .map(|result| result.unwrap_or(JArray!["error", "invalid"])) ++ .collect(), ++ ) + }); + } +- + + #[test] + fn one_rule() { +@@ -171,7 +181,6 @@ + }); + } + +- + #[test] + fn stylesheet_from_bytes() { + pub struct EncodingRs; +@@ -184,8 +193,7 @@ + } + + fn is_utf16_be_or_le(encoding: &Self::Encoding) -> bool { +- *encoding == encoding_rs::UTF_16LE || +- *encoding == encoding_rs::UTF_16BE ++ *encoding == encoding_rs::UTF_16LE || *encoding == encoding_rs::UTF_16BE + } + + fn from_label(ascii_label: &[u8]) -> Option { +@@ -193,37 +201,45 @@ + } + } + +- +- run_raw_json_tests(include_str!("css-parsing-tests/stylesheet_bytes.json"), +- |input, expected| { +- let map = match input { +- Json::Object(map) => map, +- _ => panic!("Unexpected JSON") +- }; +- +- let result = { +- let css = get_string(&map, "css_bytes").unwrap().chars().map(|c| { +- assert!(c as u32 <= 0xFF); +- c as u8 +- }).collect::>(); +- let protocol_encoding_label = get_string(&map, "protocol_encoding") +- .map(|s| s.as_bytes()); +- let environment_encoding = get_string(&map, "environment_encoding") +- .map(|s| s.as_bytes()) +- .and_then(EncodingRs::from_label); +- +- let encoding = stylesheet_encoding::( +- &css, protocol_encoding_label, environment_encoding); +- let (css_unicode, used_encoding, _) = encoding.decode(&css); +- let mut input = ParserInput::new(&css_unicode); +- let input = &mut Parser::new(&mut input); +- let rules = RuleListParser::new_for_stylesheet(input, JsonParser) +- .map(|result| result.unwrap_or(JArray!["error", "invalid"])) +- .collect::>(); +- JArray![rules, used_encoding.name().to_lowercase()] +- }; +- assert_json_eq(result, expected, &Json::Object(map).to_string()); +- }); ++ run_raw_json_tests( ++ include_str!("css-parsing-tests/stylesheet_bytes.json"), ++ |input, expected| { ++ let map = match input { ++ Json::Object(map) => map, ++ _ => panic!("Unexpected JSON"), ++ }; ++ ++ let result = { ++ let css = get_string(&map, "css_bytes") ++ .unwrap() ++ .chars() ++ .map(|c| { ++ assert!(c as u32 <= 0xFF); ++ c as u8 ++ }) ++ .collect::>(); ++ let protocol_encoding_label = ++ get_string(&map, "protocol_encoding").map(|s| s.as_bytes()); ++ let environment_encoding = get_string(&map, "environment_encoding") ++ .map(|s| s.as_bytes()) ++ .and_then(EncodingRs::from_label); ++ ++ let encoding = stylesheet_encoding::( ++ &css, ++ protocol_encoding_label, ++ environment_encoding, ++ ); ++ let (css_unicode, used_encoding, _) = encoding.decode(&css); ++ let mut input = ParserInput::new(&css_unicode); ++ let input = &mut Parser::new(&mut input); ++ let rules = RuleListParser::new_for_stylesheet(input, JsonParser) ++ .map(|result| result.unwrap_or(JArray!["error", "invalid"])) ++ .collect::>(); ++ JArray![rules, used_encoding.name().to_lowercase()] ++ }; ++ assert_json_eq(result, expected, &Json::Object(map).to_string()); ++ }, ++ ); + + fn get_string<'a>(map: &'a json::Object, key: &str) -> Option<&'a str> { + match map.get(key) { +@@ -234,7 +250,6 @@ + } + } + } +- + + #[test] + fn expect_no_error_token() { +@@ -256,16 +271,17 @@ + assert!(Parser::new(&mut input).expect_no_error_token().is_err()); + } + +- + /// https://github.com/servo/rust-cssparser/issues/71 + #[test] + fn outer_block_end_consumed() { + let mut input = ParserInput::new("(calc(true))"); + let mut input = Parser::new(&mut input); + assert!(input.expect_parenthesis_block().is_ok()); +- assert!(input.parse_nested_block(|input| { +- input.expect_function_matching("calc").map_err(Into::>::into) +- }).is_ok()); ++ assert!(input ++ .parse_nested_block(|input| input ++ .expect_function_matching("calc") ++ .map_err(Into::>::into)) ++ .is_ok()); + println!("{:?}", input.position()); + assert!(input.next().is_err()); + } +@@ -275,7 +291,7 @@ + fn bad_url_slice_out_of_bounds() { + let mut input = ParserInput::new("url(\u{1}\\"); + let mut parser = Parser::new(&mut input); +- let result = parser.next_including_whitespace_and_comments(); // This used to panic ++ let result = parser.next_including_whitespace_and_comments(); // This used to panic + assert_eq!(result, Ok(&Token::BadUrl("\u{1}\\".into()))); + } + +@@ -284,27 +300,33 @@ + fn bad_url_slice_not_at_char_boundary() { + let mut input = ParserInput::new("url(9\n۰"); + let mut parser = Parser::new(&mut input); +- let result = parser.next_including_whitespace_and_comments(); // This used to panic ++ let result = parser.next_including_whitespace_and_comments(); // This used to panic + assert_eq!(result, Ok(&Token::BadUrl("9\n۰".into()))); + } + + #[test] + fn unquoted_url_escaping() { +- let token = Token::UnquotedUrl("\ +- \x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\ +- \x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \ +- !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\ +- ^_`abcdefghijklmnopqrstuvwxyz{|}~\x7fé\ +- ".into()); ++ let token = Token::UnquotedUrl( ++ "\ ++ \x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\ ++ \x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \ ++ !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]\ ++ ^_`abcdefghijklmnopqrstuvwxyz{|}~\x7fé\ ++ " ++ .into(), ++ ); + let serialized = token.to_css_string(); +- assert_eq!(serialized, "\ +- url(\ +- \\1 \\2 \\3 \\4 \\5 \\6 \\7 \\8 \\9 \\a \\b \\c \\d \\e \\f \\10 \ +- \\11 \\12 \\13 \\14 \\15 \\16 \\17 \\18 \\19 \\1a \\1b \\1c \\1d \\1e \\1f \\20 \ +- !\\\"#$%&\\'\\(\\)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]\ +- ^_`abcdefghijklmnopqrstuvwxyz{|}~\\7f é\ +- )\ +- "); ++ assert_eq!( ++ serialized, ++ "\ ++ url(\ ++ \\1 \\2 \\3 \\4 \\5 \\6 \\7 \\8 \\9 \\a \\b \\c \\d \\e \\f \\10 \ ++ \\11 \\12 \\13 \\14 \\15 \\16 \\17 \\18 \\19 \\1a \\1b \\1c \\1d \\1e \\1f \\20 \ ++ !\\\"#$%&\\'\\(\\)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]\ ++ ^_`abcdefghijklmnopqrstuvwxyz{|}~\\7f é\ ++ )\ ++ " ++ ); + let mut input = ParserInput::new(&serialized); + assert_eq!(Parser::new(&mut input).next(), Ok(&token)); + } +@@ -332,43 +354,47 @@ + assert!(parse(&mut input).is_err()); + } + +- + fn run_color_tests) -> Json>(json_data: &str, to_json: F) { + run_json_tests(json_data, |input| { +- let result: Result<_, ParseError<()>> = input.parse_entirely(|i| { +- Color::parse(i).map_err(Into::into) +- }); ++ let result: Result<_, ParseError<()>> = ++ input.parse_entirely(|i| Color::parse(i).map_err(Into::into)); + to_json(result.map_err(|_| ())) + }); + } + +- + #[test] + fn color3() { +- run_color_tests(include_str!("css-parsing-tests/color3.json"), |c| c.ok().to_json()) +-} +- ++ run_color_tests(include_str!("css-parsing-tests/color3.json"), |c| { ++ c.ok().to_json() ++ }) ++} + + #[test] + fn color3_hsl() { +- run_color_tests(include_str!("css-parsing-tests/color3_hsl.json"), |c| c.ok().to_json()) +-} +- ++ run_color_tests(include_str!("css-parsing-tests/color3_hsl.json"), |c| { ++ c.ok().to_json() ++ }) ++} + + /// color3_keywords.json is different: R, G and B are in 0..255 rather than 0..1 + #[test] + fn color3_keywords() { +- run_color_tests(include_str!("css-parsing-tests/color3_keywords.json"), |c| c.ok().to_json()) +-} +- ++ run_color_tests( ++ include_str!("css-parsing-tests/color3_keywords.json"), ++ |c| c.ok().to_json(), ++ ) ++} + + #[test] + fn nth() { + run_json_tests(include_str!("css-parsing-tests/An+B.json"), |input| { +- input.parse_entirely(|i| { +- let result: Result<_, ParseError<()>> = parse_nth(i).map_err(Into::into); +- result +- }).ok().to_json() ++ input ++ .parse_entirely(|i| { ++ let result: Result<_, ParseError<()>> = parse_nth(i).map_err(Into::into); ++ result ++ }) ++ .ok() ++ .to_json() + }); + } + +@@ -388,7 +414,6 @@ + }); + } + +- + #[test] + fn serializer_not_preserving_comments() { + serializer(false) +@@ -400,44 +425,59 @@ + } + + fn serializer(preserve_comments: bool) { +- run_json_tests(include_str!("css-parsing-tests/component_value_list.json"), |input| { +- fn write_to(mut previous_token: TokenSerializationType, +- input: &mut Parser, +- string: &mut String, +- preserve_comments: bool) { +- while let Ok(token) = if preserve_comments { +- input.next_including_whitespace_and_comments().map(|t| t.clone()) +- } else { +- input.next_including_whitespace().map(|t| t.clone()) +- } { +- let token_type = token.serialization_type(); +- if !preserve_comments && previous_token.needs_separator_when_before(token_type) { +- string.push_str("/**/") +- } +- previous_token = token_type; +- token.to_css(string).unwrap(); +- let closing_token = match token { +- Token::Function(_) | Token::ParenthesisBlock => Some(Token::CloseParenthesis), +- Token::SquareBracketBlock => Some(Token::CloseSquareBracket), +- Token::CurlyBracketBlock => Some(Token::CloseCurlyBracket), +- _ => None +- }; +- if let Some(closing_token) = closing_token { +- let result: Result<_, ParseError<()>> = input.parse_nested_block(|input| { +- write_to(previous_token, input, string, preserve_comments); +- Ok(()) +- }); +- result.unwrap(); +- closing_token.to_css(string).unwrap(); ++ run_json_tests( ++ include_str!("css-parsing-tests/component_value_list.json"), ++ |input| { ++ fn write_to( ++ mut previous_token: TokenSerializationType, ++ input: &mut Parser, ++ string: &mut String, ++ preserve_comments: bool, ++ ) { ++ while let Ok(token) = if preserve_comments { ++ input ++ .next_including_whitespace_and_comments() ++ .map(|t| t.clone()) ++ } else { ++ input.next_including_whitespace().map(|t| t.clone()) ++ } { ++ let token_type = token.serialization_type(); ++ if !preserve_comments && previous_token.needs_separator_when_before(token_type) ++ { ++ string.push_str("/**/") ++ } ++ previous_token = token_type; ++ token.to_css(string).unwrap(); ++ let closing_token = match token { ++ Token::Function(_) | Token::ParenthesisBlock => { ++ Some(Token::CloseParenthesis) ++ } ++ Token::SquareBracketBlock => Some(Token::CloseSquareBracket), ++ Token::CurlyBracketBlock => Some(Token::CloseCurlyBracket), ++ _ => None, ++ }; ++ if let Some(closing_token) = closing_token { ++ let result: Result<_, ParseError<()>> = input.parse_nested_block(|input| { ++ write_to(previous_token, input, string, preserve_comments); ++ Ok(()) ++ }); ++ result.unwrap(); ++ closing_token.to_css(string).unwrap(); ++ } + } + } +- } +- let mut serialized = String::new(); +- write_to(TokenSerializationType::nothing(), input, &mut serialized, preserve_comments); +- let mut input = ParserInput::new(&serialized); +- let parser = &mut Parser::new(&mut input); +- Json::Array(component_values_to_json(parser)) +- }); ++ let mut serialized = String::new(); ++ write_to( ++ TokenSerializationType::nothing(), ++ input, ++ &mut serialized, ++ preserve_comments, ++ ); ++ let mut input = ParserInput::new(&serialized); ++ let parser = &mut Parser::new(&mut input); ++ Json::Array(component_values_to_json(parser)) ++ }, ++ ); + } + + #[test] +@@ -497,36 +537,90 @@ + "b\"" + )); + let mut input = Parser::new(&mut input); +- assert_eq!(input.current_source_location(), SourceLocation { line: 0, column: 1 }); +- assert_eq!(input.next_including_whitespace(), Ok(&Token::Ident("fo00o".into()))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 3 }); +- assert_eq!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(" "))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 4 }); +- assert_eq!(input.next_including_whitespace(), Ok(&Token::Ident("bar".into()))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 7 }); +- assert_eq!(input.next_including_whitespace_and_comments(), Ok(&Token::Comment("\n"))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 3 }); +- assert_eq!(input.next_including_whitespace(), Ok(&Token::Ident("baz".into()))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 6 }); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 0, column: 1 } ++ ); ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::Ident("fo00o".into())) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 1, column: 3 } ++ ); ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::WhiteSpace(" ")) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 1, column: 4 } ++ ); ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::Ident("bar".into())) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 1, column: 7 } ++ ); ++ assert_eq!( ++ input.next_including_whitespace_and_comments(), ++ Ok(&Token::Comment("\n")) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 2, column: 3 } ++ ); ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::Ident("baz".into())) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 2, column: 6 } ++ ); + let state = input.state(); + +- assert_eq!(input.next_including_whitespace(), Ok(&Token::WhiteSpace("\r\n\n"))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 4, column: 1 }); +- +- assert_eq!(state.source_location(), SourceLocation { line: 2, column: 6 }); +- +- assert_eq!(input.next_including_whitespace(), Ok(&Token::UnquotedUrl("u".into()))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 6, column: 2 }); +- +- assert_eq!(input.next_including_whitespace(), Ok(&Token::QuotedString("ab".into()))); +- assert_eq!(input.current_source_location(), SourceLocation { line: 7, column: 3 }); ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::WhiteSpace("\r\n\n")) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 4, column: 1 } ++ ); ++ ++ assert_eq!( ++ state.source_location(), ++ SourceLocation { line: 2, column: 6 } ++ ); ++ ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::UnquotedUrl("u".into())) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 6, column: 2 } ++ ); ++ ++ assert_eq!( ++ input.next_including_whitespace(), ++ Ok(&Token::QuotedString("ab".into())) ++ ); ++ assert_eq!( ++ input.current_source_location(), ++ SourceLocation { line: 7, column: 3 } ++ ); + assert!(input.next_including_whitespace().is_err()); + } + + #[test] + fn overflow() { ++ use std::f32; + use std::iter::repeat; +- use std::f32; + + let css = r" + 2147483646 +@@ -551,7 +645,8 @@ + -3.40282347e+38 + -3.402824e+38 + +- ".replace("{309 zeros}", &repeat('0').take(309).collect::()); ++ " ++ .replace("{309 zeros}", &repeat('0').take(309).collect::()); + let mut input = ParserInput::new(&css); + let mut input = Parser::new(&mut input); + +@@ -586,9 +681,11 @@ + let mut input = Parser::new(&mut input); + assert_eq!(input.next(), Ok(&Token::CurlyBracketBlock)); + assert!({ +- let result: Result<_, ParseError<()>> = input.parse_until_after(Delimiter::Semicolon, |_| Ok(42)); ++ let result: Result<_, ParseError<()>> = ++ input.parse_until_after(Delimiter::Semicolon, |_| Ok(42)); + result +- }.is_err()); ++ } ++ .is_err()); + assert_eq!(input.next(), Ok(&Token::Comma)); + assert!(input.next().is_err()); + } +@@ -603,9 +700,18 @@ + + // Replacement character + assert_eq!(Token::Ident("\u{FFFD}".into()).to_css_string(), "\u{FFFD}"); +- assert_eq!(Token::Ident("a\u{FFFD}".into()).to_css_string(), "a\u{FFFD}"); +- assert_eq!(Token::Ident("\u{FFFD}b".into()).to_css_string(), "\u{FFFD}b"); +- assert_eq!(Token::Ident("a\u{FFFD}b".into()).to_css_string(), "a\u{FFFD}b"); ++ assert_eq!( ++ Token::Ident("a\u{FFFD}".into()).to_css_string(), ++ "a\u{FFFD}" ++ ); ++ assert_eq!( ++ Token::Ident("\u{FFFD}b".into()).to_css_string(), ++ "\u{FFFD}b" ++ ); ++ assert_eq!( ++ Token::Ident("a\u{FFFD}b".into()).to_css_string(), ++ "a\u{FFFD}b" ++ ); + + // Number prefix + assert_eq!(Token::Ident("0a".into()).to_css_string(), "\\30 a"); +@@ -647,30 +753,52 @@ + assert_eq!(Token::Ident("--a".into()).to_css_string(), "--a"); + + // Various tests +- assert_eq!(Token::Ident("\x01\x02\x1E\x1F".into()).to_css_string(), "\\1 \\2 \\1e \\1f "); +- assert_eq!(Token::Ident("\u{0080}\x2D\x5F\u{00A9}".into()).to_css_string(), "\u{0080}\x2D\x5F\u{00A9}"); ++ assert_eq!( ++ Token::Ident("\x01\x02\x1E\x1F".into()).to_css_string(), ++ "\\1 \\2 \\1e \\1f " ++ ); ++ assert_eq!( ++ Token::Ident("\u{0080}\x2D\x5F\u{00A9}".into()).to_css_string(), ++ "\u{0080}\x2D\x5F\u{00A9}" ++ ); + assert_eq!(Token::Ident("\x7F\u{0080}\u{0081}\u{0082}\u{0083}\u{0084}\u{0085}\u{0086}\u{0087}\u{0088}\u{0089}\ + \u{008A}\u{008B}\u{008C}\u{008D}\u{008E}\u{008F}\u{0090}\u{0091}\u{0092}\u{0093}\u{0094}\u{0095}\u{0096}\ + \u{0097}\u{0098}\u{0099}\u{009A}\u{009B}\u{009C}\u{009D}\u{009E}\u{009F}".into()).to_css_string(), + "\\7f \u{0080}\u{0081}\u{0082}\u{0083}\u{0084}\u{0085}\u{0086}\u{0087}\u{0088}\u{0089}\u{008A}\u{008B}\u{008C}\ + \u{008D}\u{008E}\u{008F}\u{0090}\u{0091}\u{0092}\u{0093}\u{0094}\u{0095}\u{0096}\u{0097}\u{0098}\u{0099}\ + \u{009A}\u{009B}\u{009C}\u{009D}\u{009E}\u{009F}"); +- assert_eq!(Token::Ident("\u{00A0}\u{00A1}\u{00A2}".into()).to_css_string(), "\u{00A0}\u{00A1}\u{00A2}"); +- assert_eq!(Token::Ident("a0123456789b".into()).to_css_string(), "a0123456789b"); +- assert_eq!(Token::Ident("abcdefghijklmnopqrstuvwxyz".into()).to_css_string(), "abcdefghijklmnopqrstuvwxyz"); +- assert_eq!(Token::Ident("ABCDEFGHIJKLMNOPQRSTUVWXYZ".into()).to_css_string(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); +- assert_eq!(Token::Ident("\x20\x21\x78\x79".into()).to_css_string(), "\\ \\!xy"); ++ assert_eq!( ++ Token::Ident("\u{00A0}\u{00A1}\u{00A2}".into()).to_css_string(), ++ "\u{00A0}\u{00A1}\u{00A2}" ++ ); ++ assert_eq!( ++ Token::Ident("a0123456789b".into()).to_css_string(), ++ "a0123456789b" ++ ); ++ assert_eq!( ++ Token::Ident("abcdefghijklmnopqrstuvwxyz".into()).to_css_string(), ++ "abcdefghijklmnopqrstuvwxyz" ++ ); ++ assert_eq!( ++ Token::Ident("ABCDEFGHIJKLMNOPQRSTUVWXYZ".into()).to_css_string(), ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ ); ++ assert_eq!( ++ Token::Ident("\x20\x21\x78\x79".into()).to_css_string(), ++ "\\ \\!xy" ++ ); + + // astral symbol (U+1D306 TETRAGRAM FOR CENTRE) +- assert_eq!(Token::Ident("\u{1D306}".into()).to_css_string(), "\u{1D306}"); ++ assert_eq!( ++ Token::Ident("\u{1D306}".into()).to_css_string(), ++ "\u{1D306}" ++ ); + } + + impl ToJson for Color { + fn to_json(&self) -> json::Json { + match *self { +- Color::RGBA(ref rgba) => { +- [rgba.red, rgba.green, rgba.blue, rgba.alpha].to_json() +- }, ++ Color::RGBA(ref rgba) => [rgba.red, rgba.green, rgba.blue, rgba.alpha].to_json(), + Color::CurrentColor => "currentcolor".to_json(), + } + } +@@ -687,7 +815,7 @@ + let mut input = Parser::new(&mut input); + input.look_for_var_or_env_functions(); + +- let result = input.try(|input| input.expect_url()); ++ let result = input.try_parse(|input| input.expect_url()); + + assert!(result.is_ok()); + +@@ -695,7 +823,6 @@ + (result.is_ok(), input.seen_var_or_env_functions()) + }) + } +- + + #[cfg(feature = "bench")] + #[bench] +@@ -720,15 +847,18 @@ + } + let mut input = ParserInput::new(&input); + let mut input = Parser::new(&mut input); +- while let Ok(..) = input.next() { } ++ while let Ok(..) = input.next() {} + } + + impl<'i> DeclarationParser<'i> for JsonParser { + type Declaration = Json; + type Error = (); + +- fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) +- -> Result> { ++ fn parse_value<'t>( ++ &mut self, ++ name: CowRcStr<'i>, ++ input: &mut Parser<'i, 't>, ++ ) -> Result> { + let mut value = vec![]; + let mut important = false; + loop { +@@ -743,7 +873,7 @@ + if parse_important(input).is_ok() { + if input.is_exhausted() { + important = true; +- break ++ break; + } + } + input.reset(&start); +@@ -751,15 +881,10 @@ + } + value.push(one_component_value_to_json(token, input)); + } else { +- break ++ break; + } + } +- Ok(JArray![ +- "declaration", +- name, +- value, +- important, +- ]) ++ Ok(JArray!["declaration", name, value, important,]) + } + } + +@@ -769,8 +894,11 @@ + type AtRule = Json; + type Error = (); + +- fn parse_prelude<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) +- -> Result, Vec>, ParseError<'i, ()>> { ++ fn parse_prelude<'t>( ++ &mut self, ++ name: CowRcStr<'i>, ++ input: &mut Parser<'i, 't>, ++ ) -> Result, Vec>, ParseError<'i, ()>> { + let prelude = vec![ + "at-rule".to_json(), + name.to_json(), +@@ -785,11 +913,7 @@ + } + } + +- fn rule_without_block( +- &mut self, +- mut prelude: Vec, +- _location: SourceLocation, +- ) -> Json { ++ fn rule_without_block(&mut self, mut prelude: Vec, _location: SourceLocation) -> Json { + prelude.push(Json::Null); + Json::Array(prelude) + } +@@ -810,7 +934,10 @@ + type QualifiedRule = Json; + type Error = (); + +- fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result, ParseError<'i, ()>> { ++ fn parse_prelude<'t>( ++ &mut self, ++ input: &mut Parser<'i, 't>, ++ ) -> Result, ParseError<'i, ()>> { + Ok(component_values_to_json(input)) + } + +@@ -843,16 +970,24 @@ + value: value, + int_value: int_value, + has_sign: has_sign, +- }.to_css_string().to_json(), +- match int_value { Some(i) => i.to_json(), None => value.to_json() }, +- match int_value { Some(_) => "integer", None => "number" }.to_json() ++ } ++ .to_css_string() ++ .to_json(), ++ match int_value { ++ Some(i) => i.to_json(), ++ None => value.to_json(), ++ }, ++ match int_value { ++ Some(_) => "integer", ++ None => "number", ++ } ++ .to_json(), + ] + } + + fn nested(input: &mut Parser) -> Vec { +- let result: Result<_, ParseError<()>> = input.parse_nested_block(|input| { +- Ok(component_values_to_json(input)) +- }); ++ let result: Result<_, ParseError<()>> = ++ input.parse_nested_block(|input| Ok(component_values_to_json(input))); + result.unwrap() + } + +@@ -866,17 +1001,30 @@ + Token::Delim('\\') => "\\".to_json(), + Token::Delim(value) => value.to_string().to_json(), + +- Token::Number { value, int_value, has_sign } => Json::Array({ ++ Token::Number { ++ value, ++ int_value, ++ has_sign, ++ } => Json::Array({ + let mut v = vec!["number".to_json()]; + v.extend(numeric(value, int_value, has_sign)); + v + }), +- Token::Percentage { unit_value, int_value, has_sign } => Json::Array({ ++ Token::Percentage { ++ unit_value, ++ int_value, ++ has_sign, ++ } => Json::Array({ + let mut v = vec!["percentage".to_json()]; + v.extend(numeric(unit_value * 100., int_value, has_sign)); + v + }), +- Token::Dimension { value, int_value, has_sign, unit } => Json::Array({ ++ Token::Dimension { ++ value, ++ int_value, ++ has_sign, ++ unit, ++ } => Json::Array({ + let mut v = vec!["dimension".to_json()]; + v.extend(numeric(value, int_value, has_sign)); + v.push(unit.to_json()); +@@ -955,12 +1103,13 @@ + // For all j and k, inputs[i].1[j] should parse the same as inputs[i].1[k] + // when we use delimiters inputs[i].0. + let inputs = vec![ +- (Delimiter::Bang | Delimiter::Semicolon, +- // Note that the ';extra' is fine, because the ';' acts the same as +- // the end of input. +- vec!["token stream;extra", "token stream!", "token stream"]), +- (Delimiter::Bang | Delimiter::Semicolon, +- vec![";", "!", ""]), ++ ( ++ Delimiter::Bang | Delimiter::Semicolon, ++ // Note that the ';extra' is fine, because the ';' acts the same as ++ // the end of input. ++ vec!["token stream;extra", "token stream!", "token stream"], ++ ), ++ (Delimiter::Bang | Delimiter::Semicolon, vec![";", "!", ""]), + ]; + for equivalent in inputs { + for (j, x) in equivalent.1.iter().enumerate() { +@@ -978,7 +1127,7 @@ + let oy = iy.next(); + assert_eq!(ox, oy); + if let Err(_) = ox { +- break ++ break; + } + } + Ok(()) +@@ -1012,14 +1161,46 @@ + fn parser_with_line_number_offset() { + let mut input = ParserInput::new_with_line_number_offset("ident\nident", 72); + let mut parser = Parser::new(&mut input); +- assert_eq!(parser.current_source_location(), SourceLocation { line: 72, column: 1 }); +- assert_eq!(parser.next_including_whitespace_and_comments(), Ok(&Token::Ident("ident".into()))); +- assert_eq!(parser.current_source_location(), SourceLocation { line: 72, column: 6 }); +- assert_eq!(parser.next_including_whitespace_and_comments(), +- Ok(&Token::WhiteSpace("\n".into()))); +- assert_eq!(parser.current_source_location(), SourceLocation { line: 73, column: 1 }); +- assert_eq!(parser.next_including_whitespace_and_comments(), Ok(&Token::Ident("ident".into()))); +- assert_eq!(parser.current_source_location(), SourceLocation { line: 73, column: 6 }); ++ assert_eq!( ++ parser.current_source_location(), ++ SourceLocation { ++ line: 72, ++ column: 1 ++ } ++ ); ++ assert_eq!( ++ parser.next_including_whitespace_and_comments(), ++ Ok(&Token::Ident("ident".into())) ++ ); ++ assert_eq!( ++ parser.current_source_location(), ++ SourceLocation { ++ line: 72, ++ column: 6 ++ } ++ ); ++ assert_eq!( ++ parser.next_including_whitespace_and_comments(), ++ Ok(&Token::WhiteSpace("\n".into())) ++ ); ++ assert_eq!( ++ parser.current_source_location(), ++ SourceLocation { ++ line: 73, ++ column: 1 ++ } ++ ); ++ assert_eq!( ++ parser.next_including_whitespace_and_comments(), ++ Ok(&Token::Ident("ident".into())) ++ ); ++ assert_eq!( ++ parser.current_source_location(), ++ SourceLocation { ++ line: 73, ++ column: 6 ++ } ++ ); + } + + #[test] +@@ -1028,23 +1209,31 @@ + let mut parser = Parser::new(&mut input); + parser.skip_cdc_and_cdo(); + assert_eq!(parser.next(), Ok(&Token::Ident("x".into()))); +- assert_eq!(parser.next(), Err(BasicParseError { +- kind: BasicParseErrorKind::EndOfInput, +- location: SourceLocation { line: 0, column: 5 } +- })); ++ assert_eq!( ++ parser.next(), ++ Err(BasicParseError { ++ kind: BasicParseErrorKind::EndOfInput, ++ location: SourceLocation { line: 0, column: 5 } ++ }) ++ ); + } + + #[test] + fn parse_entirely_reports_first_error() { + #[derive(PartialEq, Debug)] +- enum E { Foo } ++ enum E { ++ Foo, ++ } + let mut input = ParserInput::new("ident"); + let mut parser = Parser::new(&mut input); + let result: Result<(), _> = parser.parse_entirely(|p| Err(p.new_custom_error(E::Foo))); +- assert_eq!(result, Err(ParseError { +- kind: ParseErrorKind::Custom(E::Foo), +- location: SourceLocation { line: 0, column: 1 }, +- })); ++ assert_eq!( ++ result, ++ Err(ParseError { ++ kind: ParseErrorKind::Custom(E::Foo), ++ location: SourceLocation { line: 0, column: 1 }, ++ }) ++ ); + } + + #[test] +@@ -1053,21 +1242,23 @@ + ("/*# sourceMappingURL=here*/", Some("here")), + ("/*# sourceMappingURL=here */", Some("here")), + ("/*@ sourceMappingURL=here*/", Some("here")), +- ("/*@ sourceMappingURL=there*/ /*# sourceMappingURL=here*/", Some("here")), ++ ( ++ "/*@ sourceMappingURL=there*/ /*# sourceMappingURL=here*/", ++ Some("here"), ++ ), + ("/*# sourceMappingURL=here there */", Some("here")), + ("/*# sourceMappingURL= here */", Some("")), + ("/*# sourceMappingURL=*/", Some("")), + ("/*# sourceMappingUR=here */", None), + ("/*! sourceMappingURL=here */", None), + ("/*# sourceMappingURL = here */", None), +- ("/* # sourceMappingURL=here */", None) ++ ("/* # sourceMappingURL=here */", None), + ]; + + for test in tests { + let mut input = ParserInput::new(test.0); + let mut parser = Parser::new(&mut input); +- while let Ok(_) = parser.next_including_whitespace() { +- } ++ while let Ok(_) = parser.next_including_whitespace() {} + assert_eq!(parser.current_source_map_url(), test.1); + } + } +@@ -1085,14 +1276,13 @@ + ("/*# sourceMappingUR=here */", None), + ("/*! sourceURL=here */", None), + ("/*# sourceURL = here */", None), +- ("/* # sourceURL=here */", None) ++ ("/* # sourceURL=here */", None), + ]; + + for test in tests { + let mut input = ParserInput::new(test.0); + let mut parser = Parser::new(&mut input); +- while let Ok(_) = parser.next_including_whitespace() { +- } ++ while let Ok(_) = parser.next_including_whitespace() {} + assert_eq!(parser.current_source_url(), test.1); + } + } +@@ -1158,8 +1348,15 @@ + // Read all tokens. + loop { + match parser.next() { +- Err(BasicParseError { kind: BasicParseErrorKind::EndOfInput, .. }) => { break; } +- Err(_) => { assert!(false); } ++ Err(BasicParseError { ++ kind: BasicParseErrorKind::EndOfInput, ++ .. ++ }) => { ++ break; ++ } ++ Err(_) => { ++ assert!(false); ++ } + Ok(_) => {} + }; + } +diff --git a/third_party/rust/cssparser/src/tokenizer.rs b/third_party/rust/cssparser/src/tokenizer.rs +--- a/third_party/rust/cssparser/src/tokenizer.rs ++++ b/third_party/rust/cssparser/src/tokenizer.rs +@@ -4,15 +4,13 @@ + + // https://drafts.csswg.org/css-syntax/#tokenization + ++use std::char; ++use std::i32; + use std::ops::Range; +-use std::char; +-#[allow(unused_imports)] use std::ascii::AsciiExt; +-use std::i32; +- ++ ++use self::Token::*; ++use cow_rc_str::CowRcStr; + use parser::ParserState; +-use cow_rc_str::CowRcStr; +-use self::Token::*; +- + + /// One of the pieces the CSS input is broken into. + /// +@@ -20,7 +18,6 @@ + /// and avoid allocating/copying when possible. + #[derive(PartialEq, Debug, Clone)] + pub enum Token<'a> { +- + /// A [``](https://drafts.csswg.org/css-syntax/#ident-token-diagram) + Ident(CowRcStr<'a>), + +@@ -37,7 +34,7 @@ + /// A [``](https://drafts.csswg.org/css-syntax/#hash-token-diagram) with the type flag set to "id" + /// + /// The value does not include the `#` marker. +- IDHash(CowRcStr<'a>), // Hash that is a valid ID selector. ++ IDHash(CowRcStr<'a>), // Hash that is a valid ID selector. + + /// A [``](https://drafts.csswg.org/css-syntax/#string-token-diagram) + /// +@@ -94,7 +91,7 @@ + int_value: Option, + + /// The unit, e.g. "px" in `12px` +- unit: CowRcStr<'a> ++ unit: CowRcStr<'a>, + }, + + /// A [``](https://drafts.csswg.org/css-syntax/#whitespace-token-diagram) +@@ -109,13 +106,13 @@ + Comment(&'a str), + + /// A `:` `` +- Colon, // : ++ Colon, // : + + /// A `;` `` +- Semicolon, // ; ++ Semicolon, // ; + + /// A `,` `` +- Comma, // , ++ Comma, // , + + /// A `~=` [``](https://drafts.csswg.org/css-syntax/#include-match-token-diagram) + IncludeMatch, +@@ -180,7 +177,6 @@ + /// this token is always unmatched and indicates a parse error. + CloseCurlyBracket, + } +- + + impl<'a> Token<'a> { + /// Return whether this token represents a parse error. +@@ -196,7 +192,6 @@ + ) + } + } +- + + #[derive(Clone)] + pub struct Tokenizer<'a> { +@@ -220,7 +215,6 @@ + SeenAtLeastOne, + } + +- + impl<'a> Tokenizer<'a> { + #[inline] + pub fn new(input: &str) -> Tokenizer { +@@ -255,9 +249,7 @@ + #[inline] + pub fn see_function(&mut self, name: &str) { + if self.var_or_env_functions == SeenStatus::LookingForThem { +- if name.eq_ignore_ascii_case("var") || +- name.eq_ignore_ascii_case("env") +- { ++ if name.eq_ignore_ascii_case("var") || name.eq_ignore_ascii_case("env") { + self.var_or_env_functions = SeenStatus::SeenAtLeastOne; + } + } +@@ -340,12 +332,16 @@ + + // If false, `tokenizer.next_char()` will not panic. + #[inline] +- fn is_eof(&self) -> bool { !self.has_at_least(0) } ++ fn is_eof(&self) -> bool { ++ !self.has_at_least(0) ++ } + + // If true, the input has at least `n` bytes left *after* the current one. + // That is, `tokenizer.char_at(n)` will not panic. + #[inline] +- fn has_at_least(&self, n: usize) -> bool { self.position + n < self.input.len() } ++ fn has_at_least(&self, n: usize) -> bool { ++ self.position + n < self.input.len() ++ } + + // Advance over N bytes in the input. This function can advance + // over ASCII bytes (excluding newlines), or UTF-8 sequence +@@ -367,7 +363,9 @@ + + // Assumes non-EOF + #[inline] +- fn next_byte_unchecked(&self) -> u8 { self.byte_at(0) } ++ fn next_byte_unchecked(&self) -> u8 { ++ self.byte_at(0) ++ } + + #[inline] + fn byte_at(&self, offset: usize) -> u8 { +@@ -435,8 +433,8 @@ + + #[inline] + fn has_newline_at(&self, offset: usize) -> bool { +- self.position + offset < self.input.len() && +- matches!(self.byte_at(offset), b'\n' | b'\r' | b'\x0C') ++ self.position + offset < self.input.len() ++ && matches!(self.byte_at(offset), b'\n' | b'\r' | b'\x0C') + } + + #[inline] +@@ -446,7 +444,9 @@ + self.position += len_utf8; + // Note that due to the special case for the 4-byte sequence + // intro, we must use wrapping add here. +- self.current_line_start_position = self.current_line_start_position.wrapping_add(len_utf8 - c.len_utf16()); ++ self.current_line_start_position = self ++ .current_line_start_position ++ .wrapping_add(len_utf8 - c.len_utf16()); + c + } + +@@ -520,7 +520,6 @@ + #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] + pub struct SourcePosition(pub(crate) usize); + +- + /// The line and column number for a given position within the input. + #[derive(PartialEq, Eq, Debug, Clone, Copy)] + pub struct SourceLocation { +@@ -532,10 +531,9 @@ + pub column: u32, + } + +- + fn next_token<'a>(tokenizer: &mut Tokenizer<'a>) -> Result, ()> { + if tokenizer.is_eof() { +- return Err(()) ++ return Err(()); + } + let b = tokenizer.next_byte_unchecked(); + let token = match_byte! { b, +@@ -671,7 +669,6 @@ + Ok(token) + } + +- + fn consume_whitespace<'a>(tokenizer: &mut Tokenizer<'a>, newline: bool) -> Token<'a> { + let start_position = tokenizer.position(); + if newline { +@@ -696,7 +693,6 @@ + WhiteSpace(tokenizer.slice_from(start_position)) + } + +- + // Check for sourceMappingURL or sourceURL comments and update the + // tokenizer appropriately. + fn check_for_source_map<'a>(tokenizer: &mut Tokenizer<'a>, contents: &'a str) { +@@ -706,9 +702,9 @@ + // If there is a source map directive, extract the URL. + if contents.starts_with(directive) || contents.starts_with(directive_old) { + let contents = &contents[directive.len()..]; +- tokenizer.source_map_url = contents.split(|c| { +- c == ' ' || c == '\t' || c == '\x0C' || c == '\r' || c == '\n' +- }).next() ++ tokenizer.source_map_url = contents ++ .split(|c| c == ' ' || c == '\t' || c == '\x0C' || c == '\r' || c == '\n') ++ .next() + } + + let directive = "# sourceURL="; +@@ -717,14 +713,14 @@ + // If there is a source map directive, extract the URL. + if contents.starts_with(directive) || contents.starts_with(directive_old) { + let contents = &contents[directive.len()..]; +- tokenizer.source_url = contents.split(|c| { +- c == ' ' || c == '\t' || c == '\x0C' || c == '\r' || c == '\n' +- }).next() ++ tokenizer.source_url = contents ++ .split(|c| c == ' ' || c == '\t' || c == '\x0C' || c == '\r' || c == '\n') ++ .next() + } + } + + fn consume_comment<'a>(tokenizer: &mut Tokenizer<'a>) -> &'a str { +- tokenizer.advance(2); // consume "/*" ++ tokenizer.advance(2); // consume "/*" + let start_position = tokenizer.position(); + while !tokenizer.is_eof() { + match_byte! { tokenizer.next_byte_unchecked(), +@@ -757,21 +753,22 @@ + fn consume_string<'a>(tokenizer: &mut Tokenizer<'a>, single_quote: bool) -> Token<'a> { + match consume_quoted_string(tokenizer, single_quote) { + Ok(value) => QuotedString(value), +- Err(value) => BadString(value) +- } +-} +- ++ Err(value) => BadString(value), ++ } ++} + + /// Return `Err(())` on syntax error (ie. unescaped newline) +-fn consume_quoted_string<'a>(tokenizer: &mut Tokenizer<'a>, single_quote: bool) +- -> Result, CowRcStr<'a>> { +- tokenizer.advance(1); // Skip the initial quote +- // start_pos is at code point boundary, after " or ' ++fn consume_quoted_string<'a>( ++ tokenizer: &mut Tokenizer<'a>, ++ single_quote: bool, ++) -> Result, CowRcStr<'a>> { ++ tokenizer.advance(1); // Skip the initial quote ++ // start_pos is at code point boundary, after " or ' + let start_pos = tokenizer.position(); + let mut string_bytes; + loop { + if tokenizer.is_eof() { +- return Ok(tokenizer.slice_from(start_pos).into()) ++ return Ok(tokenizer.slice_from(start_pos).into()); + } + match_byte! { tokenizer.next_byte_unchecked(), + b'"' => { +@@ -869,29 +866,28 @@ + + Ok( + // string_bytes is well-formed UTF-8, see other comments. +- unsafe { from_utf8_release_unchecked(string_bytes) }.into() ++ unsafe { from_utf8_release_unchecked(string_bytes) }.into(), + ) + } +- + + #[inline] + fn is_ident_start(tokenizer: &mut Tokenizer) -> bool { +- !tokenizer.is_eof() && match_byte! { tokenizer.next_byte_unchecked(), +- b'a'...b'z' | b'A'...b'Z' | b'_' | b'\0' => { true }, +- b'-' => { +- tokenizer.has_at_least(1) && match_byte! { tokenizer.byte_at(1), +- b'a'...b'z' | b'A'...b'Z' | b'-' | b'_' | b'\0' => { +- true +- } +- b'\\' => { !tokenizer.has_newline_at(1) } +- b => { !b.is_ascii() }, +- } +- }, +- b'\\' => { !tokenizer.has_newline_at(1) }, +- b => { !b.is_ascii() }, +- } +-} +- ++ !tokenizer.is_eof() ++ && match_byte! { tokenizer.next_byte_unchecked(), ++ b'a'...b'z' | b'A'...b'Z' | b'_' | b'\0' => { true }, ++ b'-' => { ++ tokenizer.has_at_least(1) && match_byte! { tokenizer.byte_at(1), ++ b'a'...b'z' | b'A'...b'Z' | b'-' | b'_' | b'\0' => { ++ true ++ } ++ b'\\' => { !tokenizer.has_newline_at(1) } ++ b => { !b.is_ascii() }, ++ } ++ }, ++ b'\\' => { !tokenizer.has_newline_at(1) }, ++ b => { !b.is_ascii() }, ++ } ++} + + fn consume_ident_like<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> { + let value = consume_name(tokenizer); +@@ -914,7 +910,7 @@ + let mut value_bytes; + loop { + if tokenizer.is_eof() { +- return tokenizer.slice_from(start_pos).into() ++ return tokenizer.slice_from(start_pos).into(); + } + match_byte! { tokenizer.next_byte_unchecked(), + b'a'...b'z' | b'A'...b'Z' | b'0'...b'9' | b'_' | b'-' => { tokenizer.advance(1) }, +@@ -1019,37 +1015,37 @@ + integral_part = integral_part * 10. + digit as f64; + tokenizer.advance(1); + if tokenizer.is_eof() { +- break ++ break; + } + } + + let mut is_integer = true; + + let mut fractional_part: f64 = 0.; +- if tokenizer.has_at_least(1) && tokenizer.next_byte_unchecked() == b'.' +- && matches!(tokenizer.byte_at(1), b'0'...b'9') { ++ if tokenizer.has_at_least(1) ++ && tokenizer.next_byte_unchecked() == b'.' ++ && matches!(tokenizer.byte_at(1), b'0'...b'9') ++ { + is_integer = false; +- tokenizer.advance(1); // Consume '.' ++ tokenizer.advance(1); // Consume '.' + let mut factor = 0.1; + while let Some(digit) = byte_to_decimal_digit(tokenizer.next_byte_unchecked()) { + fractional_part += digit as f64 * factor; + factor *= 0.1; + tokenizer.advance(1); + if tokenizer.is_eof() { +- break ++ break; + } + } + } + + let mut value = sign * (integral_part + fractional_part); + +- if tokenizer.has_at_least(1) +- && matches!(tokenizer.next_byte_unchecked(), b'e' | b'E') { +- +- if matches!(tokenizer.byte_at(1), b'0'...b'9') || +- (tokenizer.has_at_least(2) +- && matches!(tokenizer.byte_at(1), b'+' | b'-') +- && matches!(tokenizer.byte_at(2), b'0'...b'9')) ++ if tokenizer.has_at_least(1) && matches!(tokenizer.next_byte_unchecked(), b'e' | b'E') { ++ if matches!(tokenizer.byte_at(1), b'0'...b'9') ++ || (tokenizer.has_at_least(2) ++ && matches!(tokenizer.byte_at(1), b'+' | b'-') ++ && matches!(tokenizer.byte_at(2), b'0'...b'9')) + { + is_integer = false; + tokenizer.advance(1); +@@ -1066,7 +1062,7 @@ + exponent = exponent * 10. + digit as f64; + tokenizer.advance(1); + if tokenizer.is_eof() { +- break ++ break; + } + } + value *= f64::powf(10., sign * exponent); +@@ -1091,7 +1087,7 @@ + unit_value: (value / 100.) as f32, + int_value: int_value, + has_sign: has_sign, +- } ++ }; + } + let value = value as f32; + if is_ident_start(tokenizer) { +@@ -1110,7 +1106,6 @@ + } + } + } +- + + #[inline] + unsafe fn from_utf8_release_unchecked(string_bytes: Vec) -> String { +@@ -1134,7 +1129,7 @@ + Some(item) => item, + None => { + tokenizer.position = tokenizer.input.len(); +- break ++ break; + } + }; + match_byte! { b, +@@ -1176,9 +1171,9 @@ + if found_printable_char { + // This function only consumed ASCII (whitespace) bytes, + // so the current position is a code point boundary. +- return Ok(consume_unquoted_url_internal(tokenizer)) ++ return Ok(consume_unquoted_url_internal(tokenizer)); + } else { +- return Ok(UnquotedUrl("".into())) ++ return Ok(UnquotedUrl("".into())); + } + + fn consume_unquoted_url_internal<'a>(tokenizer: &mut Tokenizer<'a>) -> Token<'a> { +@@ -1187,7 +1182,7 @@ + let mut string_bytes: Vec; + loop { + if tokenizer.is_eof() { +- return UnquotedUrl(tokenizer.slice_from(start_pos).into()) ++ return UnquotedUrl(tokenizer.slice_from(start_pos).into()); + } + match_byte! { tokenizer.next_byte_unchecked(), + b' ' | b'\t' | b'\n' | b'\r' | b'\x0C' => { +@@ -1274,14 +1269,15 @@ + } + UnquotedUrl( + // string_bytes is well-formed UTF-8, see other comments. +- unsafe { from_utf8_release_unchecked(string_bytes) }.into() ++ unsafe { from_utf8_release_unchecked(string_bytes) }.into(), + ) + } + +- fn consume_url_end<'a>(tokenizer: &mut Tokenizer<'a>, +- start_pos: SourcePosition, +- string: CowRcStr<'a>) +- -> Token<'a> { ++ fn consume_url_end<'a>( ++ tokenizer: &mut Tokenizer<'a>, ++ start_pos: SourcePosition, ++ string: CowRcStr<'a>, ++ ) -> Token<'a> { + while !tokenizer.is_eof() { + match_byte! { tokenizer.next_byte_unchecked(), + b')' => { +@@ -1339,24 +1335,29 @@ + digits += 1; + tokenizer.advance(1); + } +- None => break ++ None => break, + } + } + (value, digits) + } +- + + // Same constraints as consume_escape except it writes into `bytes` the result + // instead of returning it. + fn consume_escape_and_write(tokenizer: &mut Tokenizer, bytes: &mut Vec) { +- bytes.extend(consume_escape(tokenizer).encode_utf8(&mut [0; 4]).as_bytes()) ++ bytes.extend( ++ consume_escape(tokenizer) ++ .encode_utf8(&mut [0; 4]) ++ .as_bytes(), ++ ) + } + + // Assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed + // and that the next input character has already been verified + // to not be a newline. + fn consume_escape(tokenizer: &mut Tokenizer) -> char { +- if tokenizer.is_eof() { return '\u{FFFD}' } // Escaped EOF ++ if tokenizer.is_eof() { ++ return '\u{FFFD}'; ++ } // Escaped EOF + match_byte! { tokenizer.next_byte_unchecked(), + b'0'...b'9' | b'A'...b'F' | b'a'...b'f' => { + let (c, _) = consume_hex_digits(tokenizer); +diff --git a/third_party/rust/cssparser/src/unicode_range.rs b/third_party/rust/cssparser/src/unicode_range.rs +--- a/third_party/rust/cssparser/src/unicode_range.rs ++++ b/third_party/rust/cssparser/src/unicode_range.rs +@@ -4,10 +4,10 @@ + + //! https://drafts.csswg.org/css-syntax/#urange + +-use {Parser, ToCss, BasicParseError}; + use std::char; + use std::fmt; + use tokenizer::Token; ++use {BasicParseError, Parser, ToCss}; + + /// One contiguous range of code points. + /// +@@ -44,7 +44,10 @@ + + let range = match parse_concatenated(concatenated_tokens.as_bytes()) { + Ok(range) => range, +- Err(()) => return Err(input.new_basic_unexpected_token_error(Token::Ident(concatenated_tokens.into()))), ++ Err(()) => { ++ return Err(input ++ .new_basic_unexpected_token_error(Token::Ident(concatenated_tokens.into()))) ++ } + }; + if range.end > char::MAX as u32 || range.start > range.end { + Err(input.new_basic_unexpected_token_error(Token::Ident(concatenated_tokens.into()))) +@@ -61,23 +64,21 @@ + match input.next_including_whitespace()?.clone() { + Token::Ident(_) => {} + Token::Delim('?') => {} +- t => return Err(input.new_basic_unexpected_token_error(t)) ++ t => return Err(input.new_basic_unexpected_token_error(t)), + } + parse_question_marks(input) + } +- Token::Dimension { .. } => { +- parse_question_marks(input) +- } ++ Token::Dimension { .. } => parse_question_marks(input), + Token::Number { .. } => { + let after_number = input.state(); + match input.next_including_whitespace() { + Ok(&Token::Delim('?')) => parse_question_marks(input), + Ok(&Token::Dimension { .. }) => {} + Ok(&Token::Number { .. }) => {} +- _ => input.reset(&after_number) ++ _ => input.reset(&after_number), + } + } +- t => return Err(input.new_basic_unexpected_token_error(t)) ++ t => return Err(input.new_basic_unexpected_token_error(t)), + } + Ok(()) + } +@@ -90,7 +91,7 @@ + Ok(&Token::Delim('?')) => {} + _ => { + input.reset(&start); +- return ++ return; + } + } + } +@@ -99,13 +100,13 @@ + fn parse_concatenated(text: &[u8]) -> Result { + let mut text = match text.split_first() { + Some((&b'+', text)) => text, +- _ => return Err(()) ++ _ => return Err(()), + }; + let (first_hex_value, hex_digit_count) = consume_hex(&mut text); + let question_marks = consume_question_marks(&mut text); + let consumed = hex_digit_count + question_marks; + if consumed == 0 || consumed > 6 { +- return Err(()) ++ return Err(()); + } + + if question_marks > 0 { +@@ -113,13 +114,13 @@ + return Ok(UnicodeRange { + start: first_hex_value << (question_marks * 4), + end: ((first_hex_value + 1) << (question_marks * 4)) - 1, +- }) ++ }); + } + } else if text.is_empty() { + return Ok(UnicodeRange { + start: first_hex_value, + end: first_hex_value, +- }) ++ }); + } else { + if let Some((&b'-', mut text)) = text.split_first() { + let (second_hex_value, hex_digit_count) = consume_hex(&mut text); +@@ -127,7 +128,7 @@ + return Ok(UnicodeRange { + start: first_hex_value, + end: second_hex_value, +- }) ++ }); + } + } + } +@@ -143,7 +144,7 @@ + digits += 1; + *text = rest + } else { +- break ++ break; + } + } + (value, digits) +@@ -165,7 +166,10 @@ + } + + impl ToCss for UnicodeRange { +- fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { ++ fn to_css(&self, dest: &mut W) -> fmt::Result ++ where ++ W: fmt::Write, ++ { + write!(dest, "U+{:X}", self.start)?; + if self.end != self.start { + write!(dest, "-{:X}", self.end)?; + diff --git a/tar_stamps b/tar_stamps index a5feedc..b0c6082 100644 --- a/tar_stamps +++ b/tar_stamps @@ -1,8 +1,8 @@ PRODUCT="thunderbird" CHANNEL="esr68" -VERSION="68.1.1" +VERSION="68.1.2" VERSION_SUFFIX="" -RELEASE_TAG="41c0a3653f95cf6158a2b49ab7cb19327c50e9e8" +RELEASE_TAG="2e34f364630f1f65724bb6e70616b95a041c47ea" PREV_VERSION="" PREV_VERSION_SUFFIX="" #SKIP_LOCALES="" # Uncomment to skip l10n and compare-locales-generation diff --git a/thunderbird-68.1.1.source.tar.xz b/thunderbird-68.1.1.source.tar.xz deleted file mode 100644 index 5f7a797..0000000 --- a/thunderbird-68.1.1.source.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4f27fec94b2565a1d1da1c90975327a3d56e5918d517cc25bd8a5dd1a81983bb -size 330615656 diff --git a/thunderbird-68.1.1.source.tar.xz.asc b/thunderbird-68.1.1.source.tar.xz.asc deleted file mode 100644 index 077b15c..0000000 --- a/thunderbird-68.1.1.source.tar.xz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEECXsxMHeuYqAvhNpN8aZmj7t9Vy4FAl2KK6QACgkQ8aZmj7t9 -Vy60WBAAjqeEGvftvGemlGodK7fg6caRZQt49TQawplpSzF00JeF2ZGZ9wo41x5d -ekXAlK8GG9reNArPOw4PkVLG4caOaaF0LL3l3zYjs/u7zP4Tl88tHohAYEL7ejZT -iPSgU41IC3qRJdWC0JY4rtwLI2MSXNyBbFpbqfkyGaDh96QPbp5dM0+g5u90qYPB -aVVmoTblED5qH/ahKLyHAFiJ7ua8z4+3FpoZCLqtPHmfozSKeTxolcdtTS4Io9uL -5YyzNI9ayFy1bIecIlh7aK5Rmuw7WOdrFTXNihensMs17Aw1nJh/G+BqGlboi5A3 -lgt9cN+lH/xOLr6m2AcoiOFaULCQfuVEAwCbos9AHo4uKw59Uyq2JB1kWAnArrhQ -b+3CpCmyl5KJh4qagSgvFbqm08tEE1A0a7/SD1ArL5CZa3mgwFlkLHWox+JZZYTF -slF8rtLzzWNeP3ZbYUzmnA4igiLcW6L82ysMcnqigwauzqMJ7eNx9umaC5fnRFn/ -0HsKlbSS5TzjRji7GZVokvcgsBA5WDfHeFYLtF/UhNQ5R4FjucAnOhHx6zwxEw4C -UdRn5Ks+hOLfgaSap1nkzGFAtPD0bO6dvJQO9lLX2aITfJISnJ6L/8z+/xZY6d+y -sClFqcBMHq2foqQO/WDb1g5mEN57TzxOmPpOR8VHm5Kg4l7MwcQ= -=k6iB ------END PGP SIGNATURE----- diff --git a/thunderbird-68.1.2.source.tar.xz b/thunderbird-68.1.2.source.tar.xz new file mode 100644 index 0000000..00ca06b --- /dev/null +++ b/thunderbird-68.1.2.source.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9444ec8718560d2b9e1b094bc57f1a8b3a275cac354ee0cf19f8cc483809d914 +size 332126436 diff --git a/thunderbird-68.1.2.source.tar.xz.asc b/thunderbird-68.1.2.source.tar.xz.asc new file mode 100644 index 0000000..a80d6d5 --- /dev/null +++ b/thunderbird-68.1.2.source.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEECXsxMHeuYqAvhNpN8aZmj7t9Vy4FAl2c6PIACgkQ8aZmj7t9 +Vy7ovg/9FVFsyCgRFYE0hNxe8BbaVxPUB0bjfTwD59uo8ILRaoYpcSOFEWMY8v4z +wH8sc8aKMPvRe5bilQsGuwTy1rhqUbcWeo75hC5+yhBcLBtlbXJPyb1hG56RPP4C +NKY8WI8fEXVHwGSbcndFPf4V0u0OVrgwOaL9ObaGY6LG7uNk7897IS9Es4hvFB/N +vulmCC23BBPcbhucx+xUlkRuoNX5kzRfmUv5O9/dyBnSiFALaQBH4jJoFbPRhOE0 +P7w+YO9LO5+JGnPv1scwtguVyBvdr1yFqlI4fS18c8kasB1BFWdqRiZ/y0z2EFnj +zq8YfWMA7C/Ivnf7Yku875Xh9mALyA9+8x1VKgah8Nk+SCVNztuoEfjy1NJOF/GY +tDIa9bAfR2/6XEQ+KTEMcEPrzoqIBS4PmAiFw9hX3Z300DoeVa6LBQ9SUHOosxiR +aTRwsmir6esWJvBBKLZ5YBa6PVqVNB1a/hQZ9NXBP3gj30IR7Knd//QL5lXlZTy0 +ttIrBSAaNs5I26zmCHk82Ol6lCwkTaNWVdfrU2IH6cZ5HUAjlvRuyq/6F2ZyHjJT +KKY6uthqQKuSvc2At9J9qpxRbKcWVPWtm9lMPcOaazRNsnOEOfu4zV/ypYJILe3k +wCwoiAaYYMxGUDmwtDjHxRut4KB7XGKJ6roqDoHR3UCfs3FJU8w= +=dnBi +-----END PGP SIGNATURE-----