зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #16752 - Report more informative CSS errors (from jdm:css-parse-error); r=SimonSapin
This requires https://github.com/servo/rust-cssparser/pull/143 for the final commit. There's no better way to split that work up, unfortunately, and it's extremely easy to bitrot. I would appreciate if we could expedite reviewing this work. This is the work necessary to enable https://bugzilla.mozilla.org/show_bug.cgi?id=1352669. It makes sense to merge it separately because it's so much effort to keep it up to date with the ongoing Stylo work. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [x] There are tests for these changes Source-Repo: https://github.com/servo/servo Source-Revision: 061cb5f48e5c93a5decf39e530aea4a566e97341 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 683cf352b472110df4b28c191e8850763334134d
This commit is contained in:
Родитель
da2db41a9c
Коммит
1f87774d78
|
@ -314,7 +314,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"azure 0.16.0 (git+https://github.com/servo/rust-azure)",
|
||||
"canvas_traits 0.0.1",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -329,7 +329,7 @@ dependencies = [
|
|||
name = "canvas_traits"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -567,14 +567,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cssparser"
|
||||
version = "0.13.7"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -586,7 +586,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1005,7 +1005,7 @@ name = "geckoservo"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1072,7 +1072,7 @@ dependencies = [
|
|||
name = "gfx_tests"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx 0.0.1",
|
||||
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style 0.0.1",
|
||||
|
@ -2158,7 +2158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "procedural-masquerade"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -2371,7 +2371,7 @@ dependencies = [
|
|||
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"deny_public_fields 0.0.1",
|
||||
"devtools_traits 0.0.1",
|
||||
"dom_struct 0.0.1",
|
||||
|
@ -2444,7 +2444,7 @@ dependencies = [
|
|||
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"canvas_traits 0.0.1",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2516,7 +2516,7 @@ name = "selectors"
|
|||
version = "0.19.0"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2898,7 +2898,7 @@ dependencies = [
|
|||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2952,7 +2952,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2972,10 +2972,11 @@ name = "style_traits"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.19.0",
|
||||
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -2985,7 +2986,7 @@ name = "stylo_tests"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"geckoservo 0.0.1",
|
||||
|
@ -3565,7 +3566,7 @@ dependencies = [
|
|||
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
|
||||
"checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
|
||||
"checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
|
||||
"checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b"
|
||||
"checksum cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a5ca71edbab09f8dc1e3d1c132717562c3b01c8598ab669183c5195bb1761"
|
||||
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
|
||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||
"checksum dbus 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4aee01fb76ada3e5e7ca642ea6664ebf7308a810739ca2aca44909a1191ac254"
|
||||
|
@ -3696,7 +3697,7 @@ dependencies = [
|
|||
"checksum plane-split 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "556929ef77bf07a9f8584d21382bcebcd6e6f5845d311824d369e1df7cf56d54"
|
||||
"checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82"
|
||||
"checksum precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf1fc3616b3ef726a847f2cd2388c646ef6a1f1ba4835c2629004da48184150"
|
||||
"checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
|
||||
"checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989"
|
||||
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
|
||||
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
|
||||
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
|
||||
|
|
|
@ -12,7 +12,7 @@ path = "lib.rs"
|
|||
[dependencies]
|
||||
azure = {git = "https://github.com/servo/rust-azure"}
|
||||
canvas_traits = {path = "../canvas_traits"}
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
euclid = "0.13"
|
||||
gleam = "0.4"
|
||||
ipc-channel = "0.7"
|
||||
|
|
|
@ -10,7 +10,7 @@ name = "canvas_traits"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
euclid = "0.13"
|
||||
heapsize = "0.4"
|
||||
heapsize_derive = "0.1"
|
||||
|
|
|
@ -35,7 +35,7 @@ byteorder = "1.0"
|
|||
canvas_traits = {path = "../canvas_traits"}
|
||||
caseless = "0.1.0"
|
||||
cookie = "0.6"
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
deny_public_fields = {path = "../deny_public_fields"}
|
||||
devtools_traits = {path = "../devtools_traits"}
|
||||
dom_struct = {path = "../dom_struct"}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use canvas_traits::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
|
||||
use cssparser::{Parser, RGBA};
|
||||
use cssparser::{Parser, ParserInput, RGBA};
|
||||
use cssparser::Color as CSSColor;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::CanvasGradientBinding;
|
||||
|
@ -53,7 +53,8 @@ impl CanvasGradientMethods for CanvasGradient {
|
|||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
let mut parser = Parser::new(&color);
|
||||
let mut input = ParserInput::new(&color);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let color = CSSColor::parse(&mut parser);
|
||||
let color = if parser.is_exhausted() {
|
||||
match color {
|
||||
|
|
|
@ -6,7 +6,7 @@ use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg};
|
|||
use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
|
||||
use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
|
||||
use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
|
||||
use cssparser::{Parser, RGBA};
|
||||
use cssparser::{Parser, ParserInput, RGBA};
|
||||
use cssparser::Color as CSSColor;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
|
||||
|
@ -463,7 +463,8 @@ impl CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
fn parse_color(&self, string: &str) -> Result<RGBA, ()> {
|
||||
let mut parser = Parser::new(&string);
|
||||
let mut input = ParserInput::new(string);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let color = CSSColor::parse(&mut parser);
|
||||
if parser.is_exhausted() {
|
||||
match color {
|
||||
|
@ -1314,7 +1315,8 @@ impl Drop for CanvasRenderingContext2D {
|
|||
}
|
||||
|
||||
pub fn parse_color(string: &str) -> Result<RGBA, ()> {
|
||||
let mut parser = Parser::new(&string);
|
||||
let mut input = ParserInput::new(string);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
match CSSColor::parse(&mut parser) {
|
||||
Ok(CSSColor::RGBA(rgba)) => {
|
||||
if parser.is_exhausted() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::{Parser, serialize_identifier};
|
||||
use cssparser::{Parser, ParserInput, serialize_identifier};
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::reflector::Reflector;
|
||||
|
@ -39,7 +39,8 @@ impl CSS {
|
|||
|
||||
/// https://drafts.csswg.org/css-conditional/#dom-css-supports
|
||||
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
|
||||
let mut input = Parser::new(&condition);
|
||||
let mut input = ParserInput::new(&condition);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let cond = parse_condition_or_declaration(&mut input);
|
||||
if let Ok(cond) = cond {
|
||||
let url = win.Document().url();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding;
|
||||
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods;
|
||||
use dom::bindings::error::ErrorResult;
|
||||
|
@ -58,7 +58,8 @@ impl CSSKeyframesRule {
|
|||
|
||||
/// Given a keyframe selector, finds the index of the first corresponding rule if any
|
||||
fn find_rule(&self, selector: &str) -> Option<usize> {
|
||||
let mut input = Parser::new(selector);
|
||||
let mut input = ParserInput::new(selector);
|
||||
let mut input = Parser::new(&mut input);
|
||||
if let Ok(sel) = KeyframeSelector::parse(&mut input) {
|
||||
let guard = self.cssrule.shared_lock().read();
|
||||
// This finds the *last* element matching a selector
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding;
|
||||
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding::CSSMediaRuleMethods;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
|
@ -69,7 +69,8 @@ impl CSSMediaRule {
|
|||
|
||||
/// https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface
|
||||
pub fn set_condition_text(&self, text: DOMString) {
|
||||
let mut input = Parser::new(&text);
|
||||
let mut input = ParserInput::new(&text);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let global = self.global();
|
||||
let win = global.as_window();
|
||||
let url = win.get_url();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use dom::bindings::codegen::Bindings::CSSSupportsRuleBinding;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use dom::bindings::js::Root;
|
||||
|
@ -55,7 +55,8 @@ impl CSSSupportsRule {
|
|||
|
||||
/// https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
|
||||
pub fn set_condition_text(&self, text: DOMString) {
|
||||
let mut input = Parser::new(&text);
|
||||
let mut input = ParserInput::new(&text);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let cond = SupportsCondition::parse(&mut input);
|
||||
if let Ok(cond) = cond {
|
||||
let global = self.global();
|
||||
|
|
|
@ -2061,7 +2061,7 @@ impl ElementMethods for Element {
|
|||
// https://dom.spec.whatwg.org/#dom-element-matches
|
||||
fn Matches(&self, selectors: DOMString) -> Fallible<bool> {
|
||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||
Err(()) => Err(Error::Syntax),
|
||||
Err(_) => Err(Error::Syntax),
|
||||
Ok(selectors) => {
|
||||
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
|
||||
Ok(matches_selector_list(&selectors, &Root::from_ref(self), &mut ctx))
|
||||
|
@ -2077,7 +2077,7 @@ impl ElementMethods for Element {
|
|||
// https://dom.spec.whatwg.org/#dom-element-closest
|
||||
fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
|
||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||
Err(()) => Err(Error::Syntax),
|
||||
Err(_) => Err(Error::Syntax),
|
||||
Ok(selectors) => {
|
||||
let root = self.upcast::<Node>();
|
||||
for element in root.inclusive_ancestors() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser as CssParser;
|
||||
use cssparser::{Parser as CssParser, ParserInput};
|
||||
use dom::attr::Attr;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods;
|
||||
|
@ -278,7 +278,8 @@ impl HTMLLinkElement {
|
|||
None => "",
|
||||
};
|
||||
|
||||
let mut css_parser = CssParser::new(&mq_str);
|
||||
let mut input = ParserInput::new(&mq_str);
|
||||
let mut css_parser = CssParser::new(&mut input);
|
||||
let win = document.window();
|
||||
let doc_url = document.url();
|
||||
let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser as CssParser;
|
||||
use cssparser::{Parser as CssParser, ParserInput};
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods;
|
||||
|
@ -91,8 +91,9 @@ impl HTMLStyleElement {
|
|||
PARSING_MODE_DEFAULT,
|
||||
doc.quirks_mode());
|
||||
let shared_lock = node.owner_doc().style_shared_lock().clone();
|
||||
let mut input = ParserInput::new(&mq_str);
|
||||
let mq = Arc::new(shared_lock.wrap(
|
||||
parse_media_query_list(&context, &mut CssParser::new(&mq_str))));
|
||||
parse_media_query_list(&context, &mut CssParser::new(&mut input))));
|
||||
let loader = StylesheetLoader::for_element(self.upcast());
|
||||
let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq,
|
||||
shared_lock, Some(&loader),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use dom::bindings::codegen::Bindings::MediaListBinding;
|
||||
use dom::bindings::codegen::Bindings::MediaListBinding::MediaListMethods;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
|
@ -71,7 +71,8 @@ impl MediaListMethods for MediaList {
|
|||
return;
|
||||
}
|
||||
// Step 3
|
||||
let mut parser = Parser::new(&value);
|
||||
let mut input = ParserInput::new(&value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let global = self.global();
|
||||
let win = global.as_window();
|
||||
let url = win.get_url();
|
||||
|
@ -107,7 +108,8 @@ impl MediaListMethods for MediaList {
|
|||
// https://drafts.csswg.org/cssom/#dom-medialist-appendmedium
|
||||
fn AppendMedium(&self, medium: DOMString) {
|
||||
// Step 1
|
||||
let mut parser = Parser::new(&medium);
|
||||
let mut input = ParserInput::new(&medium);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let global = self.global();
|
||||
let win = global.as_window();
|
||||
let url = win.get_url();
|
||||
|
@ -135,7 +137,8 @@ impl MediaListMethods for MediaList {
|
|||
// https://drafts.csswg.org/cssom/#dom-medialist-deletemedium
|
||||
fn DeleteMedium(&self, medium: DOMString) {
|
||||
// Step 1
|
||||
let mut parser = Parser::new(&medium);
|
||||
let mut input = ParserInput::new(&medium);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let global = self.global();
|
||||
let win = global.as_window();
|
||||
let url = win.get_url();
|
||||
|
|
|
@ -717,7 +717,7 @@ impl Node {
|
|||
// Step 1.
|
||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||
// Step 2.
|
||||
Err(()) => Err(Error::Syntax),
|
||||
Err(_) => Err(Error::Syntax),
|
||||
// Step 3.
|
||||
Ok(selectors) => {
|
||||
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
|
||||
|
@ -737,7 +737,7 @@ impl Node {
|
|||
// Step 1.
|
||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||
// Step 2.
|
||||
Err(()) => Err(Error::Syntax),
|
||||
Err(_) => Err(Error::Syntax),
|
||||
// Step 3.
|
||||
Ok(selectors) => {
|
||||
let mut descendants = self.traverse_preorder();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use app_units::Au;
|
||||
use base64;
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
|
||||
|
@ -1003,7 +1003,8 @@ impl WindowMethods for Window {
|
|||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-matchmedia
|
||||
fn MatchMedia(&self, query: DOMString) -> Root<MediaQueryList> {
|
||||
let mut parser = Parser::new(&query);
|
||||
let mut input = ParserInput::new(&query);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let url = self.get_url();
|
||||
let quirks_mode = self.Document().quirks_mode();
|
||||
let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media),
|
||||
|
|
|
@ -13,7 +13,7 @@ path = "lib.rs"
|
|||
app_units = "0.4.1"
|
||||
atomic_refcell = "0.1"
|
||||
canvas_traits = {path = "../canvas_traits"}
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
euclid = "0.13"
|
||||
gfx_traits = {path = "../gfx_traits"}
|
||||
heapsize = "0.4"
|
||||
|
|
|
@ -9,7 +9,7 @@ use msg::constellation_msg::PipelineId;
|
|||
use script_traits::ConstellationControlMsg;
|
||||
use servo_url::ServoUrl;
|
||||
use std::sync::{Mutex, Arc};
|
||||
use style::error_reporting::ParseErrorReporter;
|
||||
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
|
||||
#[derive(HeapSizeOf, Clone)]
|
||||
pub struct CSSErrorReporter {
|
||||
|
@ -22,12 +22,12 @@ pub struct CSSErrorReporter {
|
|||
}
|
||||
|
||||
impl ParseErrorReporter for CSSErrorReporter {
|
||||
fn report_error(&self,
|
||||
input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
message: &str,
|
||||
url: &ServoUrl,
|
||||
line_number_offset: u64) {
|
||||
fn report_error<'a>(&self,
|
||||
input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
error: ContextualParseError<'a>,
|
||||
url: &ServoUrl,
|
||||
line_number_offset: u64) {
|
||||
let location = input.source_location(position);
|
||||
let line_offset = location.line + line_number_offset as usize;
|
||||
if log_enabled!(log::LogLevel::Info) {
|
||||
|
@ -35,7 +35,7 @@ impl ParseErrorReporter for CSSErrorReporter {
|
|||
url.as_str(),
|
||||
line_offset,
|
||||
location.column,
|
||||
message)
|
||||
error.to_string())
|
||||
}
|
||||
|
||||
//TODO: report a real filename
|
||||
|
@ -44,6 +44,6 @@ impl ParseErrorReporter for CSSErrorReporter {
|
|||
"".to_owned(),
|
||||
location.line,
|
||||
location.column,
|
||||
message.to_owned()));
|
||||
error.to_string()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ gecko_like_types = []
|
|||
[dependencies]
|
||||
bitflags = "0.7"
|
||||
matches = "0.1"
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
log = "0.3"
|
||||
fnv = "1.0"
|
||||
phf = "0.7.18"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
|
||||
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
||||
use cssparser::{ParseError, BasicParseError};
|
||||
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
||||
use precomputed_hash::PrecomputedHash;
|
||||
use servo_arc::{Arc, HeaderWithLength, ThinArc};
|
||||
|
@ -43,6 +44,30 @@ fn to_ascii_lowercase(s: &str) -> Cow<str> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum SelectorParseError<'i, T> {
|
||||
PseudoElementInComplexSelector,
|
||||
NoQualifiedNameInAttributeSelector,
|
||||
TooManyCompoundSelectorComponentsInNegation,
|
||||
NegationSelectorComponentNotNamespace,
|
||||
NegationSelectorComponentNotLocalName,
|
||||
EmptySelector,
|
||||
NonSimpleSelectorInNegation,
|
||||
UnexpectedTokenInAttributeSelector,
|
||||
PseudoElementExpectedColon,
|
||||
PseudoElementExpectedIdent,
|
||||
UnsupportedPseudoClass,
|
||||
UnexpectedIdent(Cow<'i, str>),
|
||||
ExpectedNamespace,
|
||||
Custom(T),
|
||||
}
|
||||
|
||||
impl<'a, T> Into<ParseError<'a, SelectorParseError<'a, T>>> for SelectorParseError<'a, T> {
|
||||
fn into(self) -> ParseError<'a, SelectorParseError<'a, T>> {
|
||||
ParseError::Custom(self)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! with_all_bounds {
|
||||
(
|
||||
[ $( $InSelector: tt )* ]
|
||||
|
@ -97,26 +122,30 @@ with_bounds! {
|
|||
[From<String> + for<'a> From<&'a str>]
|
||||
}
|
||||
|
||||
pub trait Parser {
|
||||
pub trait Parser<'i> {
|
||||
type Impl: SelectorImpl;
|
||||
type Error: 'i;
|
||||
|
||||
/// This function can return an "Err" pseudo-element in order to support CSS2.1
|
||||
/// pseudo-elements.
|
||||
fn parse_non_ts_pseudo_class(&self, _name: Cow<str>)
|
||||
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ()> {
|
||||
Err(())
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
|
||||
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
|
||||
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
|
||||
}
|
||||
|
||||
fn parse_non_ts_functional_pseudo_class
|
||||
(&self, _name: Cow<str>, _arguments: &mut CssParser)
|
||||
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ()>
|
||||
fn parse_non_ts_functional_pseudo_class<'t>
|
||||
(&self, name: Cow<'i, str>, _arguments: &mut CssParser<'i, 't>)
|
||||
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
|
||||
ParseError<'i, SelectorParseError<'i, Self::Error>>>
|
||||
{
|
||||
Err(())
|
||||
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
|
||||
}
|
||||
|
||||
fn parse_pseudo_element(&self, _name: Cow<str>)
|
||||
-> Result<<Self::Impl as SelectorImpl>::PseudoElement, ()> {
|
||||
Err(())
|
||||
fn parse_pseudo_element(&self, name: Cow<'i, str>)
|
||||
-> Result<<Self::Impl as SelectorImpl>::PseudoElement,
|
||||
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
|
||||
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
|
||||
}
|
||||
|
||||
fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
|
||||
|
@ -157,8 +186,9 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
|
|||
/// https://drafts.csswg.org/selectors/#grouping
|
||||
///
|
||||
/// Return the Selectors or Err if there is an invalid selector.
|
||||
pub fn parse<P>(parser: &P, input: &mut CssParser) -> Result<Self, ()>
|
||||
where P: Parser<Impl=Impl> {
|
||||
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E> {
|
||||
input.parse_comma_separated(|input| parse_selector(parser, input).map(SelectorAndHashes::new))
|
||||
.map(SelectorList)
|
||||
}
|
||||
|
@ -960,11 +990,11 @@ type ParseVec<Impl> = SmallVec<[Component<Impl>; 32]>;
|
|||
/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
|
||||
///
|
||||
/// `Err` means invalid selector.
|
||||
fn parse_selector<P, Impl>(
|
||||
fn parse_selector<'i, 't, P, E, Impl>(
|
||||
parser: &P,
|
||||
input: &mut CssParser)
|
||||
-> Result<Selector<Impl>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
input: &mut CssParser<'i, 't>)
|
||||
-> Result<Selector<Impl>, ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
let mut sequence = ParseVec::new();
|
||||
let mut parsed_pseudo_element;
|
||||
|
@ -983,7 +1013,7 @@ fn parse_selector<P, Impl>(
|
|||
loop {
|
||||
let position = input.position();
|
||||
match input.next_including_whitespace() {
|
||||
Err(()) => break 'outer_loop,
|
||||
Err(_e) => break 'outer_loop,
|
||||
Ok(Token::WhiteSpace(_)) => any_whitespace = true,
|
||||
Ok(Token::Delim('>')) => {
|
||||
combinator = Combinator::Child;
|
||||
|
@ -1026,12 +1056,13 @@ fn parse_selector<P, Impl>(
|
|||
|
||||
impl<Impl: SelectorImpl> Selector<Impl> {
|
||||
/// Parse a selector, without any pseudo-element.
|
||||
pub fn parse<P>(parser: &P, input: &mut CssParser) -> Result<Self, ()>
|
||||
where P: Parser<Impl=Impl>
|
||||
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>
|
||||
{
|
||||
let selector = parse_selector(parser, input)?;
|
||||
if selector.has_pseudo_element() {
|
||||
return Err(())
|
||||
return Err(ParseError::Custom(SelectorParseError::PseudoElementInComplexSelector))
|
||||
}
|
||||
Ok(selector)
|
||||
}
|
||||
|
@ -1040,9 +1071,10 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
|||
/// * `Err(())`: Invalid selector, abort
|
||||
/// * `Ok(None)`: Not a type selector, could be something else. `input` was not consumed.
|
||||
/// * `Ok(Some(vec))`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
|
||||
fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mut ParseVec<Impl>)
|
||||
-> Result<bool, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
fn parse_type_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>,
|
||||
sequence: &mut ParseVec<Impl>)
|
||||
-> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ false)? {
|
||||
None => Ok(false),
|
||||
|
@ -1100,11 +1132,12 @@ enum QNamePrefix<Impl: SelectorImpl> {
|
|||
/// * `Err(())`: Invalid selector, abort
|
||||
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
|
||||
/// * `Ok(Some((namespace, local_name)))`: `None` for the local name means a `*` universal selector
|
||||
fn parse_qualified_name<'i, 't, P, Impl>
|
||||
fn parse_qualified_name<'i, 't, P, E, Impl>
|
||||
(parser: &P, input: &mut CssParser<'i, 't>,
|
||||
in_attr_selector: bool)
|
||||
-> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
-> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
let default_namespace = |local_name| {
|
||||
let namespace = match parser.default_namespace() {
|
||||
|
@ -1122,7 +1155,8 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
|||
Ok(Token::Ident(local_name)) => {
|
||||
Ok(Some((namespace, Some(local_name))))
|
||||
},
|
||||
_ => Err(()),
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||
Err(e) => Err(ParseError::Basic(e)),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1134,7 +1168,7 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
|||
Ok(Token::Delim('|')) => {
|
||||
let prefix = from_cow_str(value);
|
||||
let result = parser.namespace_for_prefix(&prefix);
|
||||
let url = result.ok_or(())?;
|
||||
let url = result.ok_or(ParseError::Custom(SelectorParseError::ExpectedNamespace))?;
|
||||
explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
|
||||
},
|
||||
_ => {
|
||||
|
@ -1153,10 +1187,13 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
|||
Ok(Token::Delim('|')) => {
|
||||
explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
|
||||
}
|
||||
_ => {
|
||||
result => {
|
||||
input.reset(position);
|
||||
if in_attr_selector {
|
||||
Err(())
|
||||
match result {
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||
Err(e) => Err(ParseError::Basic(e)),
|
||||
}
|
||||
} else {
|
||||
default_namespace(None)
|
||||
}
|
||||
|
@ -1174,14 +1211,15 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
|||
}
|
||||
|
||||
|
||||
fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||
-> Result<Component<Impl>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||
-> Result<Component<Impl>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
let namespace;
|
||||
let local_name;
|
||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
|
||||
None => return Err(()),
|
||||
None => return Err(ParseError::Custom(SelectorParseError::NoQualifiedNameInAttributeSelector)),
|
||||
Some((_, None)) => unreachable!(),
|
||||
Some((ns, Some(ln))) => {
|
||||
local_name = ln;
|
||||
|
@ -1209,7 +1247,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
|||
let never_matches;
|
||||
match input.next() {
|
||||
// [foo]
|
||||
Err(()) => {
|
||||
Err(_) => {
|
||||
let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
|
||||
let local_name = from_cow_str(local_name);
|
||||
if let Some(namespace) = namespace {
|
||||
|
@ -1264,7 +1302,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
|||
never_matches = value.is_empty();
|
||||
operator = AttrSelectorOperator::Suffix;
|
||||
}
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedTokenInAttributeSelector.into())
|
||||
}
|
||||
|
||||
let mut case_sensitivity = parse_attribute_flags(input)?;
|
||||
|
@ -1310,23 +1348,26 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
|||
}
|
||||
|
||||
|
||||
fn parse_attribute_flags(input: &mut CssParser) -> Result<ParsedCaseSensitivity, ()> {
|
||||
fn parse_attribute_flags<'i, 't, E>(input: &mut CssParser<'i, 't>)
|
||||
-> Result<ParsedCaseSensitivity,
|
||||
ParseError<'i, SelectorParseError<'i, E>>> {
|
||||
match input.next() {
|
||||
Err(()) => Ok(ParsedCaseSensitivity::CaseSensitive),
|
||||
Err(_) => Ok(ParsedCaseSensitivity::CaseSensitive),
|
||||
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
|
||||
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
|
||||
}
|
||||
_ => Err(())
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Level 3: Parse **one** simple_selector. (Though we might insert a second
|
||||
/// implied "<defaultns>|*" type selector.)
|
||||
fn parse_negation<P, Impl>(parser: &P,
|
||||
input: &mut CssParser)
|
||||
-> Result<Component<Impl>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
fn parse_negation<'i, 't, P, E, Impl>(parser: &P,
|
||||
input: &mut CssParser<'i, 't>)
|
||||
-> Result<Component<Impl>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
let mut v = ParseVec::new();
|
||||
parse_compound_selector(parser, input, &mut v, /* inside_negation = */ true)?;
|
||||
|
@ -1334,7 +1375,7 @@ fn parse_negation<P, Impl>(parser: &P,
|
|||
if single_simple_selector(&v) {
|
||||
Ok(Component::Negation(v.into_vec().into_boxed_slice()))
|
||||
} else {
|
||||
Err(())
|
||||
Err(ParseError::Custom(SelectorParseError::NonSimpleSelectorInNegation))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1365,13 +1406,13 @@ fn single_simple_selector<Impl: SelectorImpl>(v: &[Component<Impl>]) -> bool {
|
|||
/// `Err(())` means invalid selector.
|
||||
///
|
||||
/// The boolean represent whether a pseudo-element has been parsed.
|
||||
fn parse_compound_selector<P, Impl>(
|
||||
fn parse_compound_selector<'i, 't, P, E, Impl>(
|
||||
parser: &P,
|
||||
input: &mut CssParser,
|
||||
input: &mut CssParser<'i, 't>,
|
||||
mut sequence: &mut ParseVec<Impl>,
|
||||
inside_negation: bool)
|
||||
-> Result<bool, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
-> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
// Consume any leading whitespace.
|
||||
loop {
|
||||
|
@ -1412,21 +1453,21 @@ fn parse_compound_selector<P, Impl>(
|
|||
loop {
|
||||
match input.next_including_whitespace() {
|
||||
Ok(Token::Colon) => {},
|
||||
Ok(Token::WhiteSpace(_)) | Err(()) => break,
|
||||
_ => return Err(()),
|
||||
Ok(Token::WhiteSpace(_)) | Err(_) => break,
|
||||
_ => return Err(SelectorParseError::PseudoElementExpectedColon.into()),
|
||||
}
|
||||
|
||||
// TODO(emilio): Functional pseudo-classes too?
|
||||
// We don't need it for now.
|
||||
let name = match input.next_including_whitespace() {
|
||||
Ok(Token::Ident(name)) => name,
|
||||
_ => return Err(()),
|
||||
_ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()),
|
||||
};
|
||||
|
||||
let pseudo_class =
|
||||
P::parse_non_ts_pseudo_class(parser, name)?;
|
||||
if !p.supports_pseudo_class(&pseudo_class) {
|
||||
return Err(());
|
||||
return Err(SelectorParseError::UnsupportedPseudoClass.into());
|
||||
}
|
||||
state_selectors.push(Component::NonTSPseudoClass(pseudo_class));
|
||||
}
|
||||
|
@ -1448,18 +1489,19 @@ fn parse_compound_selector<P, Impl>(
|
|||
}
|
||||
if empty {
|
||||
// An empty selector is invalid.
|
||||
Err(())
|
||||
Err(ParseError::Custom(SelectorParseError::EmptySelector))
|
||||
} else {
|
||||
Ok(pseudo)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_functional_pseudo_class<P, Impl>(parser: &P,
|
||||
input: &mut CssParser,
|
||||
name: Cow<str>,
|
||||
inside_negation: bool)
|
||||
-> Result<Component<Impl>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
fn parse_functional_pseudo_class<'i, 't, P, E, Impl>(parser: &P,
|
||||
input: &mut CssParser<'i, 't>,
|
||||
name: Cow<'i, str>,
|
||||
inside_negation: bool)
|
||||
-> Result<Component<Impl>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
match_ignore_ascii_case! { &name,
|
||||
"nth-child" => return parse_nth_pseudo_class(input, Component::NthChild),
|
||||
|
@ -1468,7 +1510,7 @@ fn parse_functional_pseudo_class<P, Impl>(parser: &P,
|
|||
"nth-last-of-type" => return parse_nth_pseudo_class(input, Component::NthLastOfType),
|
||||
"not" => {
|
||||
if inside_negation {
|
||||
return Err(())
|
||||
return Err(ParseError::Custom(SelectorParseError::UnexpectedIdent("not".into())));
|
||||
}
|
||||
return parse_negation(parser, input)
|
||||
},
|
||||
|
@ -1479,8 +1521,9 @@ fn parse_functional_pseudo_class<P, Impl>(parser: &P,
|
|||
}
|
||||
|
||||
|
||||
fn parse_nth_pseudo_class<Impl, F>(input: &mut CssParser, selector: F)
|
||||
-> Result<Component<Impl>, ()>
|
||||
fn parse_nth_pseudo_class<'i, 't, Impl, F, E>(input: &mut CssParser<'i, 't>, selector: F)
|
||||
-> Result<Component<Impl>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
|
||||
let (a, b) = parse_nth(input)?;
|
||||
Ok(selector(a, b))
|
||||
|
@ -1492,11 +1535,12 @@ where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
|
|||
/// * `Err(())`: Invalid selector, abort
|
||||
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
|
||||
/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
|
||||
fn parse_one_simple_selector<P, Impl>(parser: &P,
|
||||
input: &mut CssParser,
|
||||
inside_negation: bool)
|
||||
-> Result<Option<SimpleSelectorParseResult<Impl>>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
|
||||
input: &mut CssParser<'i, 't>,
|
||||
inside_negation: bool)
|
||||
-> Result<Option<SimpleSelectorParseResult<Impl>>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
let start_position = input.position();
|
||||
match input.next_including_whitespace() {
|
||||
|
@ -1510,7 +1554,8 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
|
|||
let class = Component::Class(from_cow_str(class));
|
||||
Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
|
||||
}
|
||||
_ => Err(()),
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||
Err(e) => Err(ParseError::Basic(e)),
|
||||
}
|
||||
}
|
||||
Ok(Token::SquareBracketBlock) => {
|
||||
|
@ -1545,10 +1590,12 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
|
|||
let pseudo = P::parse_pseudo_element(parser, name)?;
|
||||
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo)))
|
||||
}
|
||||
_ => Err(())
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||
Err(e) => Err(ParseError::Basic(e)),
|
||||
}
|
||||
}
|
||||
_ => Err(())
|
||||
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||
Err(e) => Err(ParseError::Basic(e)),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -1558,8 +1605,10 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_simple_pseudo_class<P, Impl>(parser: &P, name: Cow<str>) -> Result<Component<Impl>, ()>
|
||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
||||
fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: Cow<'i, str>)
|
||||
-> Result<Component<Impl>,
|
||||
ParseError<'i, SelectorParseError<'i, E>>>
|
||||
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||
{
|
||||
(match_ignore_ascii_case! { &name,
|
||||
"first-child" => Ok(Component::FirstChild),
|
||||
|
@ -1580,7 +1629,7 @@ fn parse_simple_pseudo_class<P, Impl>(parser: &P, name: Cow<str>) -> Result<Comp
|
|||
// NB: pub module in order to access the DummyParser
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use cssparser::{Parser as CssParser, ToCss, serialize_identifier};
|
||||
use cssparser::{Parser as CssParser, ToCss, serialize_identifier, ParserInput};
|
||||
use parser;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
|
@ -1691,32 +1740,37 @@ pub mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
impl Parser for DummyParser {
|
||||
impl<'i> Parser<'i> for DummyParser {
|
||||
type Impl = DummySelectorImpl;
|
||||
type Error = ();
|
||||
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>)
|
||||
-> Result<PseudoClass, ()> {
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||
-> Result<PseudoClass,
|
||||
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||
match_ignore_ascii_case! { &name,
|
||||
"hover" => Ok(PseudoClass::Hover),
|
||||
"active" => Ok(PseudoClass::Active),
|
||||
_ => Err(())
|
||||
_ => Err(SelectorParseError::Custom(()).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_non_ts_functional_pseudo_class(&self, name: Cow<str>,
|
||||
parser: &mut CssParser)
|
||||
-> Result<PseudoClass, ()> {
|
||||
fn parse_non_ts_functional_pseudo_class<'t>(&self, name: Cow<'i, str>,
|
||||
parser: &mut CssParser<'i, 't>)
|
||||
-> Result<PseudoClass,
|
||||
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||
match_ignore_ascii_case! { &name,
|
||||
"lang" => Ok(PseudoClass::Lang(try!(parser.expect_ident_or_string()).into_owned())),
|
||||
_ => Err(())
|
||||
_ => Err(SelectorParseError::Custom(()).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
|
||||
fn parse_pseudo_element(&self, name: Cow<'i, str>)
|
||||
-> Result<PseudoElement,
|
||||
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||
match_ignore_ascii_case! { &name,
|
||||
"before" => Ok(PseudoElement::Before),
|
||||
"after" => Ok(PseudoElement::After),
|
||||
_ => Err(())
|
||||
_ => Err(SelectorParseError::Custom(()).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1729,13 +1783,16 @@ pub mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> Result<SelectorList<DummySelectorImpl>, ()> {
|
||||
fn parse<'i>(input: &'i str) -> Result<SelectorList<DummySelectorImpl>,
|
||||
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||
parse_ns(input, &DummyParser::default())
|
||||
}
|
||||
|
||||
fn parse_ns(input: &str, parser: &DummyParser)
|
||||
-> Result<SelectorList<DummySelectorImpl>, ()> {
|
||||
let result = SelectorList::parse(parser, &mut CssParser::new(input));
|
||||
fn parse_ns<'i>(input: &'i str, parser: &DummyParser)
|
||||
-> Result<SelectorList<DummySelectorImpl>,
|
||||
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||
let mut parser_input = ParserInput::new(input);
|
||||
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
|
||||
if let Ok(ref selectors) = result {
|
||||
assert_eq!(selectors.0.len(), 1);
|
||||
assert_eq!(selectors.0[0].selector.to_css_string(), input);
|
||||
|
@ -1749,7 +1806,8 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let list = SelectorList::parse(&DummyParser::default(), &mut CssParser::new(":empty"));
|
||||
let mut input = ParserInput::new(":empty");
|
||||
let list = SelectorList::parse(&DummyParser::default(), &mut CssParser::new(&mut input));
|
||||
assert!(list.is_ok());
|
||||
}
|
||||
|
||||
|
@ -1758,9 +1816,9 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_parsing() {
|
||||
assert_eq!(parse(""), Err(())) ;
|
||||
assert_eq!(parse(":lang(4)"), Err(())) ;
|
||||
assert_eq!(parse(":lang(en US)"), Err(())) ;
|
||||
assert!(parse("").is_err()) ;
|
||||
assert!(parse(":lang(4)").is_err()) ;
|
||||
assert!(parse(":lang(en US)").is_err()) ;
|
||||
assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
Component::LocalName(LocalName {
|
||||
|
@ -1846,7 +1904,7 @@ pub mod tests {
|
|||
}
|
||||
), specificity(0, 1, 0))
|
||||
))));
|
||||
assert_eq!(parse_ns("svg|circle", &parser), Err(()));
|
||||
assert!(parse_ns("svg|circle", &parser).is_err());
|
||||
parser.ns_prefixes.insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
|
||||
assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
|
@ -1960,14 +2018,14 @@ pub mod tests {
|
|||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||
), specificity(0, 2, 1) | HAS_PSEUDO_BIT)
|
||||
))));
|
||||
assert_eq!(parse("::before:hover:active"), Err(()));
|
||||
assert_eq!(parse("::before:hover .foo"), Err(()));
|
||||
assert_eq!(parse("::before .foo"), Err(()));
|
||||
assert_eq!(parse("::before ~ bar"), Err(()));
|
||||
assert_eq!(parse("::before:active"), Err(()));
|
||||
assert!(parse("::before:hover:active").is_err());
|
||||
assert!(parse("::before:hover .foo").is_err());
|
||||
assert!(parse("::before .foo").is_err());
|
||||
assert!(parse("::before ~ bar").is_err());
|
||||
assert!(parse("::before:active").is_err());
|
||||
|
||||
// https://github.com/servo/servo/issues/15335
|
||||
assert_eq!(parse(":: before"), Err(()));
|
||||
assert!(parse(":: before").is_err());
|
||||
assert_eq!(parse("div ::after"), Ok(SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(
|
||||
Component::LocalName(LocalName {
|
||||
|
@ -1986,8 +2044,8 @@ pub mod tests {
|
|||
), (1 << 20) + (1 << 10) + (0 << 0))
|
||||
))));
|
||||
parser.default_ns = None;
|
||||
assert_eq!(parse(":not(#provel.old)"), Err(()));
|
||||
assert_eq!(parse(":not(#provel > old)"), Err(()));
|
||||
assert!(parse(":not(#provel.old)").is_err());
|
||||
assert!(parse(":not(#provel > old)").is_err());
|
||||
assert!(parse("table[rules]:not([rules = \"none\"]):not([rules = \"\"])").is_ok());
|
||||
assert_eq!(parse(":not(#provel)"), Ok(SelectorList::from_vec(vec!(
|
||||
Selector::from_vec(vec!(Component::Negation(vec!(
|
||||
|
|
|
@ -38,7 +38,7 @@ bitflags = "0.7"
|
|||
bit-vec = "0.4.3"
|
||||
byteorder = "1.0"
|
||||
cfg-if = "0.1.0"
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
encoding = {version = "0.2", optional = true}
|
||||
euclid = "0.13"
|
||||
fnv = "1.0"
|
||||
|
|
|
@ -8,20 +8,22 @@
|
|||
|
||||
use Atom;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
|
||||
use cssparser::{Parser, Token, serialize_identifier};
|
||||
use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
|
||||
use error_reporting::ContextualParseError;
|
||||
#[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
|
||||
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc;
|
||||
use parser::{ParserContext, log_css_error, Parse};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
use style_traits::{ToCss, OneOrMoreCommaSeparated};
|
||||
use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError};
|
||||
use values::CustomIdent;
|
||||
|
||||
/// Parse the prelude of an @counter-style rule
|
||||
pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
|
||||
pub fn parse_counter_style_name<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CustomIdent, ParseError<'i>> {
|
||||
macro_rules! predefined {
|
||||
($($name: expr,)+) => {
|
||||
{
|
||||
|
@ -48,8 +50,8 @@ pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
|
|||
}
|
||||
|
||||
/// Parse the body (inside `{}`) of an @counter-style rule
|
||||
pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, input: &mut Parser)
|
||||
-> Result<CounterStyleRuleData, ()> {
|
||||
pub fn parse_counter_style_body<'i, 't>(name: CustomIdent, context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<CounterStyleRuleData, ParseError<'i>> {
|
||||
let start = input.position();
|
||||
let mut rule = CounterStyleRuleData::empty(name);
|
||||
{
|
||||
|
@ -59,11 +61,11 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
|
|||
};
|
||||
let mut iter = DeclarationListParser::new(input, parser);
|
||||
while let Some(declaration) = iter.next() {
|
||||
if let Err(range) = declaration {
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported @counter-style descriptor declaration: '{}'",
|
||||
iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, context);
|
||||
if let Err(err) = declaration {
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(
|
||||
iter.input.slice(err.span), err.error);
|
||||
log_css_error(iter.input, pos, error, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,32 +77,28 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
|
|||
ref system @ System::Numeric
|
||||
if rule.symbols.is_none() => {
|
||||
let system = system.to_css_string();
|
||||
Some(format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system))
|
||||
Some(ContextualParseError::InvalidCounterStyleWithoutSymbols(system))
|
||||
}
|
||||
ref system @ System::Alphabetic |
|
||||
ref system @ System::Numeric
|
||||
if rule.symbols().unwrap().0.len() < 2 => {
|
||||
let system = system.to_css_string();
|
||||
Some(format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'",
|
||||
system))
|
||||
Some(ContextualParseError::InvalidCounterStyleNotEnoughSymbols(system))
|
||||
}
|
||||
System::Additive if rule.additive_symbols.is_none() => {
|
||||
let s = "Invalid @counter-style rule: 'system: additive' without 'additive-symbols'";
|
||||
Some(s.to_owned())
|
||||
Some(ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols)
|
||||
}
|
||||
System::Extends(_) if rule.symbols.is_some() => {
|
||||
let s = "Invalid @counter-style rule: 'system: extends …' with 'symbols'";
|
||||
Some(s.to_owned())
|
||||
Some(ContextualParseError::InvalidCounterStyleExtendsWithSymbols)
|
||||
}
|
||||
System::Extends(_) if rule.additive_symbols.is_some() => {
|
||||
let s = "Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'";
|
||||
Some(s.to_owned())
|
||||
Some(ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols)
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if let Some(message) = error {
|
||||
log_css_error(input, start, &message, context);
|
||||
Err(())
|
||||
if let Some(error) = error {
|
||||
log_css_error(input, start, error, context);
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
Ok(rule)
|
||||
}
|
||||
|
@ -112,9 +110,10 @@ struct CounterStyleRuleParser<'a, 'b: 'a> {
|
|||
}
|
||||
|
||||
/// Default methods reject all at rules.
|
||||
impl<'a, 'b> AtRuleParser for CounterStyleRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type AtRule = ();
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
}
|
||||
|
||||
macro_rules! accessor {
|
||||
|
@ -181,11 +180,13 @@ macro_rules! counter_style_descriptors {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeclarationParser for CounterStyleRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
||||
type Declaration = ();
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
||||
match_ignore_ascii_case! { name,
|
||||
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||
-> Result<(), ParseError<'i>> {
|
||||
match_ignore_ascii_case! { &*name,
|
||||
$(
|
||||
$name => {
|
||||
// DeclarationParser also calls parse_entirely
|
||||
|
@ -196,7 +197,7 @@ macro_rules! counter_style_descriptors {
|
|||
self.rule.$ident = Some(value)
|
||||
}
|
||||
)*
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -293,8 +294,9 @@ pub enum System {
|
|||
}
|
||||
|
||||
impl Parse for System {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"cyclic" => Ok(System::Cyclic),
|
||||
"numeric" => Ok(System::Numeric),
|
||||
"alphabetic" => Ok(System::Alphabetic),
|
||||
|
@ -309,7 +311,7 @@ impl Parse for System {
|
|||
Ok(System::Extends(other))
|
||||
}
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,11 +351,12 @@ pub enum Symbol {
|
|||
}
|
||||
|
||||
impl Parse for Symbol {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
match input.next() {
|
||||
Ok(Token::QuotedString(s)) => Ok(Symbol::String(s.into_owned())),
|
||||
Ok(Token::Ident(s)) => Ok(Symbol::Ident(s.into_owned())),
|
||||
_ => Err(())
|
||||
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +386,7 @@ impl Symbol {
|
|||
pub struct Negative(pub Symbol, pub Option<Symbol>);
|
||||
|
||||
impl Parse for Negative {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Ok(Negative(
|
||||
Symbol::parse(context, input)?,
|
||||
input.try(|input| Symbol::parse(context, input)).ok(),
|
||||
|
@ -409,7 +412,7 @@ impl ToCss for Negative {
|
|||
pub struct Ranges(pub Vec<Range<Option<i32>>>);
|
||||
|
||||
impl Parse for Ranges {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||
Ok(Ranges(Vec::new()))
|
||||
} else {
|
||||
|
@ -418,7 +421,7 @@ impl Parse for Ranges {
|
|||
let opt_end = parse_bound(input)?;
|
||||
if let (Some(start), Some(end)) = (opt_start, opt_end) {
|
||||
if start > end {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
Ok(opt_start..opt_end)
|
||||
|
@ -427,11 +430,12 @@ impl Parse for Ranges {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_bound(input: &mut Parser) -> Result<Option<i32>, ()> {
|
||||
fn parse_bound<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Option<i32>, ParseError<'i>> {
|
||||
match input.next() {
|
||||
Ok(Token::Number(ref v)) if v.int_value.is_some() => Ok(Some(v.int_value.unwrap())),
|
||||
Ok(Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None),
|
||||
_ => Err(())
|
||||
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,13 +475,13 @@ fn bound_to_css<W>(range: Option<i32>, dest: &mut W) -> fmt::Result where W: fmt
|
|||
pub struct Pad(pub u32, pub Symbol);
|
||||
|
||||
impl Parse for Pad {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let pad_with = input.try(|input| Symbol::parse(context, input));
|
||||
let min_length = input.expect_integer()?;
|
||||
if min_length < 0 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
let pad_with = pad_with.or_else(|()| Symbol::parse(context, input))?;
|
||||
let pad_with = pad_with.or_else(|_| Symbol::parse(context, input))?;
|
||||
Ok(Pad(min_length as u32, pad_with))
|
||||
}
|
||||
}
|
||||
|
@ -494,7 +498,7 @@ impl ToCss for Pad {
|
|||
pub struct Fallback(pub CustomIdent);
|
||||
|
||||
impl Parse for Fallback {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
parse_counter_style_name(input).map(Fallback)
|
||||
}
|
||||
}
|
||||
|
@ -510,14 +514,14 @@ impl ToCss for Fallback {
|
|||
pub struct Symbols(pub Vec<Symbol>);
|
||||
|
||||
impl Parse for Symbols {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let mut symbols = Vec::new();
|
||||
loop {
|
||||
if let Ok(s) = input.try(|input| Symbol::parse(context, input)) {
|
||||
symbols.push(s)
|
||||
} else {
|
||||
if symbols.is_empty() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
return Ok(Symbols(symbols))
|
||||
}
|
||||
|
@ -544,11 +548,11 @@ impl ToCss for Symbols {
|
|||
pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
|
||||
|
||||
impl Parse for AdditiveSymbols {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
|
||||
// FIXME maybe? https://github.com/w3c/csswg-drafts/issues/1220
|
||||
if tuples.windows(2).any(|window| window[0].weight <= window[1].weight) {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(AdditiveSymbols(tuples))
|
||||
}
|
||||
|
@ -572,13 +576,13 @@ pub struct AdditiveTuple {
|
|||
impl OneOrMoreCommaSeparated for AdditiveTuple {}
|
||||
|
||||
impl Parse for AdditiveTuple {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let symbol = input.try(|input| Symbol::parse(context, input));
|
||||
let weight = input.expect_integer()?;
|
||||
if weight < 0 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
let symbol = symbol.or_else(|()| Symbol::parse(context, input))?;
|
||||
let symbol = symbol.or_else(|_| Symbol::parse(context, input))?;
|
||||
Ok(AdditiveTuple {
|
||||
weight: weight as u32,
|
||||
symbol: symbol,
|
||||
|
@ -611,10 +615,11 @@ pub enum SpeakAs {
|
|||
}
|
||||
|
||||
impl Parse for SpeakAs {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let mut is_spell_out = false;
|
||||
let result = input.try(|input| {
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let result: Result<_, ParseError> = input.try(|input| {
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"auto" => Ok(SpeakAs::Auto),
|
||||
"bullets" => Ok(SpeakAs::Bullets),
|
||||
"numbers" => Ok(SpeakAs::Numbers),
|
||||
|
@ -624,14 +629,14 @@ impl Parse for SpeakAs {
|
|||
Err(())
|
||||
}
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
});
|
||||
if is_spell_out {
|
||||
// spell-out is not supported, but don’t parse it as a <counter-style-name>.
|
||||
// See bug 1024178.
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
result.or_else(|()| {
|
||||
result.or_else(|_| {
|
||||
Ok(SpeakAs::Other(parse_counter_style_name(input)?))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,14 +7,15 @@
|
|||
//! [custom]: https://drafts.csswg.org/css-variables/
|
||||
|
||||
use Atom;
|
||||
use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType};
|
||||
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
|
||||
use parser::ParserContext;
|
||||
use properties::{CSSWideKeyword, DeclaredValue};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use style_traits::{HasViewportPercentage, ToCss, StyleParseError, ParseError};
|
||||
use stylearc::Arc;
|
||||
|
||||
/// A custom property name is just an `Atom`.
|
||||
|
@ -131,7 +132,8 @@ impl ComputedValue {
|
|||
|
||||
impl SpecifiedValue {
|
||||
/// Parse a custom property SpecifiedValue.
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Box<Self>, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Box<Self>, ParseError<'i>> {
|
||||
let mut references = Some(HashSet::new());
|
||||
let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references));
|
||||
Ok(Box::new(SpecifiedValue {
|
||||
|
@ -146,7 +148,7 @@ impl SpecifiedValue {
|
|||
/// Parse the value of a non-custom property that contains `var()` references.
|
||||
pub fn parse_non_custom_with_var<'i, 't>
|
||||
(input: &mut Parser<'i, 't>)
|
||||
-> Result<(TokenSerializationType, Cow<'i, str>), ()> {
|
||||
-> Result<(TokenSerializationType, Cow<'i, str>), ParseError<'i>> {
|
||||
let (first_token_type, css, _) = try!(parse_self_contained_declaration_value(input, &mut None));
|
||||
Ok((first_token_type, css))
|
||||
}
|
||||
|
@ -158,7 +160,7 @@ fn parse_self_contained_declaration_value<'i, 't>
|
|||
TokenSerializationType,
|
||||
Cow<'i, str>,
|
||||
TokenSerializationType
|
||||
), ()> {
|
||||
), ParseError<'i>> {
|
||||
let start_position = input.position();
|
||||
let mut missing_closing_characters = String::new();
|
||||
let (first, last) = try!(
|
||||
|
@ -179,7 +181,7 @@ fn parse_declaration_value<'i, 't>
|
|||
(input: &mut Parser<'i, 't>,
|
||||
references: &mut Option<HashSet<Name>>,
|
||||
missing_closing_characters: &mut String)
|
||||
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
|
||||
-> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> {
|
||||
input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
|
||||
// Need at least one token
|
||||
let start_position = input.position();
|
||||
|
@ -192,14 +194,16 @@ fn parse_declaration_value<'i, 't>
|
|||
|
||||
/// Like parse_declaration_value, but accept `!` and `;` since they are only
|
||||
/// invalid at the top level
|
||||
fn parse_declaration_value_block(input: &mut Parser,
|
||||
fn parse_declaration_value_block<'i, 't>
|
||||
(input: &mut Parser<'i, 't>,
|
||||
references: &mut Option<HashSet<Name>>,
|
||||
missing_closing_characters: &mut String)
|
||||
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
|
||||
-> Result<(TokenSerializationType, TokenSerializationType),
|
||||
ParseError<'i>> {
|
||||
let mut token_start = input.position();
|
||||
let mut token = match input.next_including_whitespace_and_comments() {
|
||||
Ok(token) => token,
|
||||
Err(()) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
|
||||
Err(_) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
|
||||
};
|
||||
let first_token_type = token.serialization_type();
|
||||
loop {
|
||||
|
@ -226,13 +230,16 @@ fn parse_declaration_value_block(input: &mut Parser,
|
|||
}
|
||||
token.serialization_type()
|
||||
}
|
||||
Token::BadUrl |
|
||||
Token::BadString |
|
||||
Token::CloseParenthesis |
|
||||
Token::CloseSquareBracket |
|
||||
Token::CloseCurlyBracket => {
|
||||
return Err(())
|
||||
}
|
||||
Token::BadUrl =>
|
||||
return Err(StyleParseError::BadUrlInDeclarationValueBlock.into()),
|
||||
Token::BadString =>
|
||||
return Err(StyleParseError::BadStringInDeclarationValueBlock.into()),
|
||||
Token::CloseParenthesis =>
|
||||
return Err(StyleParseError::UnbalancedCloseParenthesisInDeclarationValueBlock.into()),
|
||||
Token::CloseSquareBracket =>
|
||||
return Err(StyleParseError::UnbalancedCloseSquareBracketInDeclarationValueBlock.into()),
|
||||
Token::CloseCurlyBracket =>
|
||||
return Err(StyleParseError::UnbalancedCloseCurlyBracketInDeclarationValueBlock.into()),
|
||||
Token::Function(ref name) => {
|
||||
if name.eq_ignore_ascii_case("var") {
|
||||
let position = input.position();
|
||||
|
@ -303,9 +310,12 @@ fn parse_declaration_value_block(input: &mut Parser,
|
|||
// If the var function is valid, return Ok((custom_property_name, fallback))
|
||||
fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
|
||||
references: &mut Option<HashSet<Name>>)
|
||||
-> Result<(), ()> {
|
||||
-> Result<(), ParseError<'i>> {
|
||||
let name = try!(input.expect_ident());
|
||||
let name = try!(parse_name(&name));
|
||||
let name: Result<_, ParseError> =
|
||||
parse_name(&name)
|
||||
.map_err(|()| SelectorParseError::UnexpectedIdent(name.clone()).into());
|
||||
let name = try!(name);
|
||||
if input.try(|input| input.expect_comma()).is_ok() {
|
||||
// Exclude `!` and `;` at the top level
|
||||
// https://drafts.csswg.org/css-syntax/#typedef-declaration-value
|
||||
|
@ -474,7 +484,8 @@ fn substitute_one(name: &Name,
|
|||
}
|
||||
let computed_value = if specified_value.references.map(|set| set.is_empty()) == Some(false) {
|
||||
let mut partial_computed_value = ComputedValue::empty();
|
||||
let mut input = Parser::new(&specified_value.css);
|
||||
let mut input = ParserInput::new(&specified_value.css);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let mut position = (input.position(), specified_value.first_token_type);
|
||||
let result = substitute_block(
|
||||
&mut input, &mut position, &mut partial_computed_value,
|
||||
|
@ -525,11 +536,11 @@ fn substitute_one(name: &Name,
|
|||
///
|
||||
/// Return `Err(())` if `input` is invalid at computed-value time.
|
||||
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
|
||||
fn substitute_block<F>(input: &mut Parser,
|
||||
position: &mut (SourcePosition, TokenSerializationType),
|
||||
partial_computed_value: &mut ComputedValue,
|
||||
substitute_one: &mut F)
|
||||
-> Result<TokenSerializationType, ()>
|
||||
fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>,
|
||||
position: &mut (SourcePosition, TokenSerializationType),
|
||||
partial_computed_value: &mut ComputedValue,
|
||||
substitute_one: &mut F)
|
||||
-> Result<TokenSerializationType, ParseError<'i>>
|
||||
where F: FnMut(&Name, &mut ComputedValue) -> Result<TokenSerializationType, ()> {
|
||||
let mut last_token_type = TokenSerializationType::nothing();
|
||||
let mut set_position_at_next_iteration = false;
|
||||
|
@ -539,7 +550,7 @@ fn substitute_block<F>(input: &mut Parser,
|
|||
if set_position_at_next_iteration {
|
||||
*position = (before_this_token, match next {
|
||||
Ok(ref token) => token.serialization_type(),
|
||||
Err(()) => TokenSerializationType::nothing(),
|
||||
Err(_) => TokenSerializationType::nothing(),
|
||||
});
|
||||
set_position_at_next_iteration = false;
|
||||
}
|
||||
|
@ -605,11 +616,12 @@ fn substitute_block<F>(input: &mut Parser,
|
|||
|
||||
/// Replace `var()` functions for a non-custom property.
|
||||
/// Return `Err(())` for invalid at computed time.
|
||||
pub fn substitute(input: &str, first_token_type: TokenSerializationType,
|
||||
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
||||
-> Result<String, ()> {
|
||||
pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
|
||||
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
||||
-> Result<String, ParseError<'i>> {
|
||||
let mut substituted = ComputedValue::empty();
|
||||
let mut input = Parser::new(input);
|
||||
let mut input = ParserInput::new(input);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let mut position = (input.position(), first_token_type);
|
||||
let last_token_type = try!(substitute_block(
|
||||
&mut input, &mut position, &mut substituted, &mut |name, substituted| {
|
||||
|
|
|
@ -6,22 +6,150 @@
|
|||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use cssparser::{Parser, SourcePosition};
|
||||
use cssparser::{Parser, SourcePosition, BasicParseError, Token, NumericValue, PercentageValue};
|
||||
use cssparser::ParseError as CssParseError;
|
||||
use log;
|
||||
use style_traits::ParseError;
|
||||
use stylesheets::UrlExtraData;
|
||||
|
||||
/// Errors that can be encountered while parsing CSS.
|
||||
pub enum ContextualParseError<'a> {
|
||||
/// A property declaration was not recognized.
|
||||
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>),
|
||||
/// A font face descriptor was not recognized.
|
||||
UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>),
|
||||
/// A keyframe rule was not valid.
|
||||
InvalidKeyframeRule(&'a str, ParseError<'a>),
|
||||
/// A keyframe property declaration was not recognized.
|
||||
UnsupportedKeyframePropertyDeclaration(&'a str, ParseError<'a>),
|
||||
/// A rule was invalid for some reason.
|
||||
InvalidRule(&'a str, ParseError<'a>),
|
||||
/// A rule was not recognized.
|
||||
UnsupportedRule(&'a str, ParseError<'a>),
|
||||
/// A viewport descriptor declaration was not recognized.
|
||||
UnsupportedViewportDescriptorDeclaration(&'a str, ParseError<'a>),
|
||||
/// A counter style descriptor declaration was not recognized.
|
||||
UnsupportedCounterStyleDescriptorDeclaration(&'a str, ParseError<'a>),
|
||||
/// A counter style rule had no symbols.
|
||||
InvalidCounterStyleWithoutSymbols(String),
|
||||
/// A counter style rule had less than two symbols.
|
||||
InvalidCounterStyleNotEnoughSymbols(String),
|
||||
/// A counter style rule did not have additive-symbols.
|
||||
InvalidCounterStyleWithoutAdditiveSymbols,
|
||||
/// A counter style rule had extends with symbols.
|
||||
InvalidCounterStyleExtendsWithSymbols,
|
||||
/// A counter style rule had extends with additive-symbols.
|
||||
InvalidCounterStyleExtendsWithAdditiveSymbols
|
||||
}
|
||||
|
||||
impl<'a> ContextualParseError<'a> {
|
||||
/// Turn a parse error into a string representation.
|
||||
pub fn to_string(&self) -> String {
|
||||
fn token_to_str(t: &Token) -> String {
|
||||
match *t {
|
||||
Token::Ident(ref i) => format!("identifier {}", i),
|
||||
Token::AtKeyword(ref kw) => format!("keyword @{}", kw),
|
||||
Token::Hash(ref h) => format!("hash #{}", h),
|
||||
Token::IDHash(ref h) => format!("id selector #{}", h),
|
||||
Token::QuotedString(ref s) => format!("quoted string \"{}\"", s),
|
||||
Token::UnquotedUrl(ref u) => format!("url {}", u),
|
||||
Token::Delim(ref d) => format!("delimiter {}", d),
|
||||
Token::Number(NumericValue { int_value: Some(i), .. }) => format!("number {}", i),
|
||||
Token::Number(ref n) => format!("number {}", n.value),
|
||||
Token::Percentage(PercentageValue { int_value: Some(i), .. }) => format!("percentage {}", i),
|
||||
Token::Percentage(ref p) => format!("percentage {}", p.unit_value),
|
||||
Token::Dimension(_, ref d) => format!("dimension {}", d),
|
||||
Token::WhiteSpace(_) => format!("whitespace"),
|
||||
Token::Comment(_) => format!("comment"),
|
||||
Token::Colon => format!("colon (:)"),
|
||||
Token::Semicolon => format!("semicolon (;)"),
|
||||
Token::Comma => format!("comma (,)"),
|
||||
Token::IncludeMatch => format!("include match (~=)"),
|
||||
Token::DashMatch => format!("dash match (|=)"),
|
||||
Token::PrefixMatch => format!("prefix match (^=)"),
|
||||
Token::SuffixMatch => format!("suffix match ($=)"),
|
||||
Token::SubstringMatch => format!("substring match (*=)"),
|
||||
Token::Column => format!("column (||)"),
|
||||
Token::CDO => format!("CDO (<!--)"),
|
||||
Token::CDC => format!("CDC (-->)"),
|
||||
Token::Function(ref f) => format!("function {}", f),
|
||||
Token::ParenthesisBlock => format!("parenthesis ("),
|
||||
Token::SquareBracketBlock => format!("square bracket ["),
|
||||
Token::CurlyBracketBlock => format!("curly bracket {{"),
|
||||
Token::BadUrl => format!("bad url parse error"),
|
||||
Token::BadString => format!("bad string parse error"),
|
||||
Token::CloseParenthesis => format!("unmatched close parenthesis"),
|
||||
Token::CloseSquareBracket => format!("unmatched close square bracket"),
|
||||
Token::CloseCurlyBracket => format!("unmatched close curly bracket"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_error_to_str(err: &ParseError) -> String {
|
||||
match *err {
|
||||
CssParseError::Basic(BasicParseError::UnexpectedToken(ref t)) =>
|
||||
format!("found unexpected {}", token_to_str(t)),
|
||||
CssParseError::Basic(BasicParseError::ExpectedToken(ref t)) =>
|
||||
format!("expected {}", token_to_str(t)),
|
||||
CssParseError::Basic(BasicParseError::EndOfInput) =>
|
||||
format!("unexpected end of input"),
|
||||
CssParseError::Basic(BasicParseError::AtRuleInvalid) =>
|
||||
format!("@ rule invalid"),
|
||||
CssParseError::Basic(BasicParseError::QualifiedRuleInvalid) =>
|
||||
format!("qualified rule invalid"),
|
||||
CssParseError::Custom(ref err) =>
|
||||
format!("{:?}", err)
|
||||
}
|
||||
}
|
||||
|
||||
match *self {
|
||||
ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err) =>
|
||||
format!("Unsupported property declaration: '{}', {}", decl,
|
||||
parse_error_to_str(err)),
|
||||
ContextualParseError::UnsupportedFontFaceDescriptor(decl, ref err) =>
|
||||
format!("Unsupported @font-face descriptor declaration: '{}', {}", decl,
|
||||
parse_error_to_str(err)),
|
||||
ContextualParseError::InvalidKeyframeRule(rule, ref err) =>
|
||||
format!("Invalid keyframe rule: '{}', {}", rule,
|
||||
parse_error_to_str(err)),
|
||||
ContextualParseError::UnsupportedKeyframePropertyDeclaration(decl, ref err) =>
|
||||
format!("Unsupported keyframe property declaration: '{}', {}", decl,
|
||||
parse_error_to_str(err)),
|
||||
ContextualParseError::InvalidRule(rule, ref err) =>
|
||||
format!("Invalid rule: '{}', {}", rule, parse_error_to_str(err)),
|
||||
ContextualParseError::UnsupportedRule(rule, ref err) =>
|
||||
format!("Unsupported rule: '{}', {}", rule, parse_error_to_str(err)),
|
||||
ContextualParseError::UnsupportedViewportDescriptorDeclaration(decl, ref err) =>
|
||||
format!("Unsupported @viewport descriptor declaration: '{}', {}", decl,
|
||||
parse_error_to_str(err)),
|
||||
ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(decl, ref err) =>
|
||||
format!("Unsupported @counter-style descriptor declaration: '{}', {}", decl,
|
||||
parse_error_to_str(err)),
|
||||
ContextualParseError::InvalidCounterStyleWithoutSymbols(ref system) =>
|
||||
format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system),
|
||||
ContextualParseError::InvalidCounterStyleNotEnoughSymbols(ref system) =>
|
||||
format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'", system),
|
||||
ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols =>
|
||||
"Invalid @counter-style rule: 'system: additive' without 'additive-symbols'".into(),
|
||||
ContextualParseError::InvalidCounterStyleExtendsWithSymbols =>
|
||||
"Invalid @counter-style rule: 'system: extends …' with 'symbols'".into(),
|
||||
ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols =>
|
||||
"Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic trait for an error reporter.
|
||||
pub trait ParseErrorReporter : Sync + Send {
|
||||
pub trait ParseErrorReporter : Sync {
|
||||
/// Called when the style engine detects an error.
|
||||
///
|
||||
/// Returns the current input being parsed, the source position it was
|
||||
/// reported from, and a message.
|
||||
fn report_error(&self,
|
||||
input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
message: &str,
|
||||
url: &UrlExtraData,
|
||||
line_number_offset: u64);
|
||||
fn report_error<'a>(&self,
|
||||
input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
error: ContextualParseError<'a>,
|
||||
url: &UrlExtraData,
|
||||
line_number_offset: u64);
|
||||
}
|
||||
|
||||
/// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log)
|
||||
|
@ -33,16 +161,16 @@ pub trait ParseErrorReporter : Sync + Send {
|
|||
pub struct RustLogReporter;
|
||||
|
||||
impl ParseErrorReporter for RustLogReporter {
|
||||
fn report_error(&self,
|
||||
input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
message: &str,
|
||||
url: &UrlExtraData,
|
||||
line_number_offset: u64) {
|
||||
fn report_error<'a>(&self,
|
||||
input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
error: ContextualParseError<'a>,
|
||||
url: &UrlExtraData,
|
||||
line_number_offset: u64) {
|
||||
if log_enabled!(log::LogLevel::Info) {
|
||||
let location = input.source_location(position);
|
||||
let line_offset = location.line + line_number_offset as usize;
|
||||
info!("Url:\t{}\n{}:{} {}", url.as_str(), line_offset, location.column, message)
|
||||
info!("Url:\t{}\n{}:{} {}", url.as_str(), line_offset, location.column, error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +179,17 @@ impl ParseErrorReporter for RustLogReporter {
|
|||
pub struct NullReporter;
|
||||
|
||||
impl ParseErrorReporter for NullReporter {
|
||||
fn report_error(&self,
|
||||
fn report_error<'a>(&self,
|
||||
_: &mut Parser,
|
||||
_: SourcePosition,
|
||||
_: &str,
|
||||
_: ContextualParseError<'a>,
|
||||
_: &UrlExtraData,
|
||||
_: u64) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an instance of the default error reporter.
|
||||
pub fn create_error_reporter() -> RustLogReporter {
|
||||
RustLogReporter
|
||||
}
|
||||
|
|
|
@ -13,12 +13,15 @@ use computed_values::{font_feature_settings, font_stretch, font_style, font_weig
|
|||
use computed_values::font_family::FamilyName;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::SourceLocation;
|
||||
use error_reporting::ContextualParseError;
|
||||
#[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors;
|
||||
#[cfg(feature = "gecko")] use cssparser::UnicodeRange;
|
||||
use parser::{ParserContext, log_css_error, Parse};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, OneOrMoreCommaSeparated};
|
||||
use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError};
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
/// A source for a font-face rule.
|
||||
|
@ -97,11 +100,11 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser, locati
|
|||
};
|
||||
let mut iter = DeclarationListParser::new(input, parser);
|
||||
while let Some(declaration) = iter.next() {
|
||||
if let Err(range) = declaration {
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported @font-face descriptor declaration: '{}'",
|
||||
iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, context);
|
||||
if let Err(err) = declaration {
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::UnsupportedFontFaceDescriptor(
|
||||
iter.input.slice(err.span), err.error);
|
||||
log_css_error(iter.input, pos, error, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,13 +157,15 @@ struct FontFaceRuleParser<'a, 'b: 'a> {
|
|||
}
|
||||
|
||||
/// Default methods reject all at rules.
|
||||
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for FontFaceRuleParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type AtRule = ();
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
}
|
||||
|
||||
impl Parse for Source {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Source, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_function_matching("local")).is_ok() {
|
||||
return input.parse_nested_block(|input| {
|
||||
FamilyName::parse(context, input)
|
||||
|
@ -247,11 +252,13 @@ macro_rules! font_face_descriptors_common {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
|
||||
type Declaration = ();
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for FontFaceRuleParser<'a, 'b> {
|
||||
type Declaration = ();
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
||||
match_ignore_ascii_case! { name,
|
||||
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||
-> Result<(), ParseError<'i>> {
|
||||
match_ignore_ascii_case! { &*name,
|
||||
$(
|
||||
$name => {
|
||||
// DeclarationParser also calls parse_entirely
|
||||
|
@ -262,7 +269,7 @@ macro_rules! font_face_descriptors_common {
|
|||
self.rule.$ident = Some(value)
|
||||
}
|
||||
)*
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use app_units::Au;
|
||||
use context::QuirksMode;
|
||||
use cssparser::{CssStringWriter, Parser, RGBA, Token};
|
||||
use cssparser::{CssStringWriter, Parser, RGBA, Token, BasicParseError};
|
||||
use euclid::Size2D;
|
||||
use font_metrics::get_metrics_provider_for_product;
|
||||
use gecko::values::convert_nscolor_to_rgba;
|
||||
|
@ -19,11 +19,12 @@ use media_queries::MediaType;
|
|||
use parser::ParserContext;
|
||||
use properties::{ComputedValues, StyleBuilder};
|
||||
use properties::longhands::font_size;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::fmt::{self, Write};
|
||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
||||
use str::starts_with_ignore_ascii_case;
|
||||
use string_cache::Atom;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use stylearc::Arc;
|
||||
use values::{CSSFloat, specified};
|
||||
|
@ -228,24 +229,25 @@ impl Resolution {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let (value, unit) = match try!(input.next()) {
|
||||
Token::Dimension(value, unit) => {
|
||||
(value.value, unit)
|
||||
(value, unit)
|
||||
},
|
||||
_ => return Err(()),
|
||||
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
};
|
||||
|
||||
if value <= 0. {
|
||||
return Err(())
|
||||
let inner_value = value.value;
|
||||
if inner_value <= 0. {
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
Ok(match_ignore_ascii_case! { &unit,
|
||||
"dpi" => Resolution::Dpi(value),
|
||||
"dppx" => Resolution::Dppx(value),
|
||||
"dpcm" => Resolution::Dpcm(value),
|
||||
_ => return Err(())
|
||||
})
|
||||
(match_ignore_ascii_case! { &unit,
|
||||
"dpi" => Ok(Resolution::Dpi(inner_value)),
|
||||
"dppx" => Ok(Resolution::Dppx(inner_value)),
|
||||
"dpcm" => Ok(Resolution::Dpcm(inner_value)),
|
||||
_ => Err(())
|
||||
}).map_err(|()| StyleParseError::UnexpectedDimension(unit).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,44 +461,51 @@ impl Expression {
|
|||
/// ```
|
||||
/// (media-feature: media-value)
|
||||
/// ```
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
try!(input.expect_parenthesis_block());
|
||||
input.parse_nested_block(|input| {
|
||||
let ident = try!(input.expect_ident());
|
||||
|
||||
let mut flags = 0;
|
||||
let mut feature_name = &*ident;
|
||||
let result = {
|
||||
let mut feature_name = &*ident;
|
||||
|
||||
// TODO(emilio): this is under a pref in Gecko.
|
||||
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
|
||||
feature_name = &feature_name[8..];
|
||||
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
|
||||
}
|
||||
// TODO(emilio): this is under a pref in Gecko.
|
||||
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
|
||||
feature_name = &feature_name[8..];
|
||||
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
|
||||
}
|
||||
|
||||
let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
|
||||
feature_name = &feature_name[4..];
|
||||
nsMediaExpression_Range::eMin
|
||||
} else if starts_with_ignore_ascii_case(feature_name, "max-") {
|
||||
feature_name = &feature_name[4..];
|
||||
nsMediaExpression_Range::eMax
|
||||
} else {
|
||||
nsMediaExpression_Range::eEqual
|
||||
};
|
||||
|
||||
let atom = Atom::from(feature_name);
|
||||
let feature =
|
||||
match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
|
||||
Some(f) => f,
|
||||
None => return Err(()),
|
||||
let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
|
||||
feature_name = &feature_name[4..];
|
||||
nsMediaExpression_Range::eMin
|
||||
} else if starts_with_ignore_ascii_case(feature_name, "max-") {
|
||||
feature_name = &feature_name[4..];
|
||||
nsMediaExpression_Range::eMax
|
||||
} else {
|
||||
nsMediaExpression_Range::eEqual
|
||||
};
|
||||
|
||||
let atom = Atom::from(feature_name);
|
||||
match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
|
||||
Some(f) => Ok((f, range)),
|
||||
None => Err(()),
|
||||
}
|
||||
};
|
||||
|
||||
let (feature, range) = match result {
|
||||
Ok((feature, range)) => (feature, range),
|
||||
Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||
};
|
||||
|
||||
if (feature.mReqFlags & !flags) != 0 {
|
||||
return Err(());
|
||||
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||
}
|
||||
|
||||
if range != nsMediaExpression_Range::eEqual &&
|
||||
feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
|
||||
return Err(());
|
||||
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||
}
|
||||
|
||||
// If there's no colon, this is a media query of the form
|
||||
|
@ -506,7 +515,7 @@ impl Expression {
|
|||
// reject them here too.
|
||||
if input.try(|i| i.expect_colon()).is_err() {
|
||||
if range != nsMediaExpression_Range::eEqual {
|
||||
return Err(())
|
||||
return Err(StyleParseError::RangedExpressionWithNoValue.into())
|
||||
}
|
||||
return Ok(Expression::new(feature, None, range));
|
||||
}
|
||||
|
@ -519,14 +528,14 @@ impl Expression {
|
|||
nsMediaFeature_ValueType::eInteger => {
|
||||
let i = input.expect_integer()?;
|
||||
if i < 0 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
MediaExpressionValue::Integer(i as u32)
|
||||
}
|
||||
nsMediaFeature_ValueType::eBoolInteger => {
|
||||
let i = input.expect_integer()?;
|
||||
if i < 0 || i > 1 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
MediaExpressionValue::BoolInteger(i == 1)
|
||||
}
|
||||
|
@ -536,14 +545,14 @@ impl Expression {
|
|||
nsMediaFeature_ValueType::eIntRatio => {
|
||||
let a = input.expect_integer()?;
|
||||
if a <= 0 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
input.expect_delim('/')?;
|
||||
|
||||
let b = input.expect_integer()?;
|
||||
if b <= 0 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
MediaExpressionValue::IntRatio(a as u32, b as u32)
|
||||
}
|
||||
|
@ -566,7 +575,7 @@ impl Expression {
|
|||
Some((_kw, value)) => {
|
||||
value
|
||||
}
|
||||
None => return Err(()),
|
||||
None => return Err(StyleParseError::UnspecifiedError.into()),
|
||||
};
|
||||
|
||||
MediaExpressionValue::Enumerated(value)
|
||||
|
|
|
@ -8,11 +8,12 @@ use cssparser::{Parser, ToCss};
|
|||
use element_state::ElementState;
|
||||
use gecko_bindings::structs::CSSPseudoClassType;
|
||||
use selector_parser::{SelectorParser, PseudoElementCascadeType};
|
||||
use selectors::parser::{Selector, SelectorMethods};
|
||||
use selectors::parser::{Selector, SelectorMethods, SelectorParseError};
|
||||
use selectors::visitor::SelectorVisitor;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
|
||||
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT};
|
||||
pub use gecko::snapshot::SnapshotMap;
|
||||
|
@ -238,17 +239,20 @@ impl ::selectors::SelectorImpl for SelectorImpl {
|
|||
type NonTSPseudoClass = NonTSPseudoClass;
|
||||
}
|
||||
|
||||
impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||
impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||
type Impl = SelectorImpl;
|
||||
type Error = StyleParseError<'i>;
|
||||
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||
macro_rules! pseudo_class_parse {
|
||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
|
||||
keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
|
||||
match_ignore_ascii_case! { &name,
|
||||
$($css => NonTSPseudoClass::$name,)*
|
||||
_ => return Err(())
|
||||
_ => return Err(::selectors::parser::SelectorParseError::UnexpectedIdent(
|
||||
name.clone()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -256,14 +260,14 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
|
||||
Ok(pseudo_class)
|
||||
} else {
|
||||
Err(())
|
||||
Err(SelectorParseError::UnexpectedIdent(name).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_non_ts_functional_pseudo_class(&self,
|
||||
name: Cow<str>,
|
||||
parser: &mut Parser)
|
||||
-> Result<NonTSPseudoClass, ()> {
|
||||
fn parse_non_ts_functional_pseudo_class<'t>(&self,
|
||||
name: Cow<'i, str>,
|
||||
parser: &mut Parser<'i, 't>)
|
||||
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||
macro_rules! pseudo_class_string_parse {
|
||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
|
||||
|
@ -289,11 +293,11 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
})?;
|
||||
// Selectors inside `:-moz-any` may not include combinators.
|
||||
if selectors.iter().flat_map(|x| x.iter_raw()).any(|s| s.is_combinator()) {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent("-moz-any".into()).into())
|
||||
}
|
||||
NonTSPseudoClass::MozAny(selectors.into_boxed_slice())
|
||||
}
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -301,13 +305,13 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
|
||||
Ok(pseudo_class)
|
||||
} else {
|
||||
Err(())
|
||||
Err(SelectorParseError::UnexpectedIdent(name).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
|
||||
fn parse_pseudo_element(&self, name: Cow<'i, str>) -> Result<PseudoElement, ParseError<'i>> {
|
||||
PseudoElement::from_slice(&name, self.in_user_agent_stylesheet())
|
||||
.ok_or(())
|
||||
.ok_or(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
|
||||
fn default_namespace(&self) -> Option<Namespace> {
|
||||
|
|
|
@ -11,7 +11,7 @@ use gecko_bindings::sugar::refptr::RefPtr;
|
|||
use parser::ParserContext;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
use stylearc::Arc;
|
||||
|
||||
/// A specified url() value for gecko. Gecko does not eagerly resolve SpecifiedUrls.
|
||||
|
@ -38,7 +38,7 @@ impl SpecifiedUrl {
|
|||
/// Returns `Err` in the case that extra_data is incomplete.
|
||||
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
||||
context: &ParserContext)
|
||||
-> Result<Self, ()> {
|
||||
-> Result<Self, ParseError<'a>> {
|
||||
Ok(SpecifiedUrl {
|
||||
serialization: Arc::new(url.into_owned()),
|
||||
extra_data: context.url_data.clone(),
|
||||
|
|
|
@ -21,7 +21,7 @@ use data::ElementData;
|
|||
use dom::{self, DescendantsBit, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
|
||||
use dom::{OpaqueNode, PresentationalHintsSynthesizer};
|
||||
use element_state::ElementState;
|
||||
use error_reporting::RustLogReporter;
|
||||
use error_reporting::create_error_reporter;
|
||||
use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
|
||||
use gecko::data::PerDocumentStyleData;
|
||||
use gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||
|
@ -416,7 +416,7 @@ impl<'le> GeckoElement<'le> {
|
|||
pub fn parse_style_attribute(value: &str,
|
||||
url_data: &UrlExtraData,
|
||||
quirks_mode: QuirksMode) -> PropertyDeclarationBlock {
|
||||
parse_style_attribute(value, url_data, &RustLogReporter, quirks_mode)
|
||||
parse_style_attribute(value, url_data, &create_error_reporter(), quirks_mode)
|
||||
}
|
||||
|
||||
fn flags(&self) -> u32 {
|
||||
|
|
|
@ -18,11 +18,14 @@ macro_rules! define_numbered_css_keyword_enum {
|
|||
|
||||
impl $crate::parser::Parse for $name {
|
||||
#[allow(missing_docs)]
|
||||
fn parse(_context: &$crate::parser::ParserContext, input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser<'i, 't>)
|
||||
-> Result<$name, ::style_traits::ParseError<'i>> {
|
||||
let ident = try!(input.expect_ident());
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
$( $css => Ok($name::$variant), )+
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| ::selectors::parser::SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,9 +52,9 @@ macro_rules! add_impls_for_keyword_enum {
|
|||
($name:ident) => {
|
||||
impl $crate::parser::Parse for $name {
|
||||
#[inline]
|
||||
fn parse(_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser)
|
||||
-> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser<'i, 't>)
|
||||
-> Result<Self, ::style_traits::ParseError<'i>> {
|
||||
$name::parse(input)
|
||||
}
|
||||
}
|
||||
|
@ -89,10 +92,10 @@ macro_rules! define_keyword_type {
|
|||
}
|
||||
|
||||
impl $crate::parser::Parse for $name {
|
||||
fn parse(_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser)
|
||||
-> Result<$name, ()> {
|
||||
input.expect_ident_matching($css).map(|_| $name)
|
||||
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser<'i, 't>)
|
||||
-> Result<$name, ::style_traits::ParseError<'i>> {
|
||||
input.expect_ident_matching($css).map(|_| $name).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
|
||||
use Atom;
|
||||
use context::QuirksMode;
|
||||
use cssparser::{Delimiter, Parser, Token};
|
||||
use cssparser::{Delimiter, Parser, Token, ParserInput};
|
||||
use parser::ParserContext;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use serialize_comma_separated_list;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
pub use servo::media_queries::{Device, Expression};
|
||||
|
@ -209,7 +210,8 @@ impl MediaQuery {
|
|||
/// Parse a media query given css input.
|
||||
///
|
||||
/// Returns an error if any of the expressions is unknown.
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<MediaQuery, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<MediaQuery, ParseError<'i>> {
|
||||
let mut expressions = vec![];
|
||||
|
||||
let qualifier = if input.try(|input| input.expect_ident_matching("only")).is_ok() {
|
||||
|
@ -221,11 +223,15 @@ impl MediaQuery {
|
|||
};
|
||||
|
||||
let media_type = match input.try(|input| input.expect_ident()) {
|
||||
Ok(ident) => try!(MediaQueryType::parse(&*ident)),
|
||||
Err(()) => {
|
||||
Ok(ident) => {
|
||||
let result: Result<_, ParseError> = MediaQueryType::parse(&*ident)
|
||||
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
|
||||
try!(result)
|
||||
}
|
||||
Err(_) => {
|
||||
// Media type is only optional if qualifier is not specified.
|
||||
if qualifier.is_some() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
// Without a media type, require at least one expression.
|
||||
|
@ -270,7 +276,7 @@ pub fn parse_media_query_list(context: &ParserContext, input: &mut Parser) -> Me
|
|||
match input.next() {
|
||||
Ok(Token::Comma) => {},
|
||||
Ok(_) => unreachable!(),
|
||||
Err(()) => break,
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +317,8 @@ impl MediaList {
|
|||
///
|
||||
/// Returns true if added, false if fail to parse the medium string.
|
||||
pub fn append_medium(&mut self, context: &ParserContext, new_medium: &str) -> bool {
|
||||
let mut parser = Parser::new(new_medium);
|
||||
let mut input = ParserInput::new(new_medium);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let new_query = match MediaQuery::parse(&context, &mut parser) {
|
||||
Ok(query) => query,
|
||||
Err(_) => { return false; }
|
||||
|
@ -329,7 +336,8 @@ impl MediaList {
|
|||
///
|
||||
/// Returns true if found and deleted, false otherwise.
|
||||
pub fn delete_medium(&mut self, context: &ParserContext, old_medium: &str) -> bool {
|
||||
let mut parser = Parser::new(old_medium);
|
||||
let mut input = ParserInput::new(old_medium);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
let old_query = match MediaQuery::parse(context, &mut parser) {
|
||||
Ok(query) => query,
|
||||
Err(_) => { return false; }
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
use context::QuirksMode;
|
||||
use cssparser::{Parser, SourcePosition, UnicodeRange};
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use style_traits::OneOrMoreCommaSeparated;
|
||||
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use style_traits::{OneOrMoreCommaSeparated, ParseError};
|
||||
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
|
||||
|
||||
bitflags! {
|
||||
|
@ -164,14 +164,14 @@ impl<'a> ParserContext<'a> {
|
|||
/// Defaults to a no-op.
|
||||
/// Set a `RUST_LOG=style::errors` environment variable
|
||||
/// to log CSS parse errors to stderr.
|
||||
pub fn log_css_error(input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
message: &str,
|
||||
parsercontext: &ParserContext) {
|
||||
pub fn log_css_error<'a>(input: &mut Parser,
|
||||
position: SourcePosition,
|
||||
error: ContextualParseError<'a>,
|
||||
parsercontext: &ParserContext) {
|
||||
let url_data = parsercontext.url_data;
|
||||
let line_number_offset = parsercontext.line_number_offset;
|
||||
parsercontext.error_reporter.report_error(input, position,
|
||||
message, url_data,
|
||||
error, url_data,
|
||||
line_number_offset);
|
||||
}
|
||||
|
||||
|
@ -183,19 +183,21 @@ pub trait Parse : Sized {
|
|||
/// Parse a value of this type.
|
||||
///
|
||||
/// Returns an error on failure.
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()>;
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>>;
|
||||
}
|
||||
|
||||
impl<T> Parse for Vec<T> where T: Parse + OneOrMoreCommaSeparated {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
input.parse_comma_separated(|input| T::parse(context, input))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a non-empty space-separated or comma-separated list of objects parsed by parse_one
|
||||
pub fn parse_space_or_comma_separated<F, T>(input: &mut Parser, mut parse_one: F)
|
||||
-> Result<Vec<T>, ()>
|
||||
where F: FnMut(&mut Parser) -> Result<T, ()> {
|
||||
pub fn parse_space_or_comma_separated<'i, 't, F, T>(input: &mut Parser<'i, 't>, mut parse_one: F)
|
||||
-> Result<Vec<T>, ParseError<'i>>
|
||||
where F: for<'ii, 'tt> FnMut(&mut Parser<'ii, 'tt>) -> Result<T, ParseError<'ii>> {
|
||||
let first = parse_one(input)?;
|
||||
let mut vec = vec![first];
|
||||
loop {
|
||||
|
@ -209,7 +211,8 @@ pub fn parse_space_or_comma_separated<F, T>(input: &mut Parser, mut parse_one: F
|
|||
Ok(vec)
|
||||
}
|
||||
impl Parse for UnicodeRange {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
UnicodeRange::parse(input)
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
UnicodeRange::parse(input).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,16 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
use context::QuirksMode;
|
||||
use cssparser::{DeclarationListParser, parse_important};
|
||||
use cssparser::{DeclarationListParser, parse_important, ParserInput};
|
||||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error};
|
||||
use properties::animated_properties::AnimationValue;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::Locked;
|
||||
use std::fmt;
|
||||
use std::slice::Iter;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
|
||||
use super::*;
|
||||
|
@ -875,7 +876,8 @@ pub fn parse_style_attribute(input: &str,
|
|||
Some(CssRuleType::Style),
|
||||
PARSING_MODE_DEFAULT,
|
||||
quirks_mode);
|
||||
parse_property_declaration_list(&context, &mut Parser::new(input))
|
||||
let mut input = ParserInput::new(input);
|
||||
parse_property_declaration_list(&context, &mut Parser::new(&mut input))
|
||||
}
|
||||
|
||||
/// Parse a given property declaration. Can result in multiple
|
||||
|
@ -896,10 +898,11 @@ pub fn parse_one_declaration_into(declarations: &mut SourcePropertyDeclaration,
|
|||
Some(CssRuleType::Style),
|
||||
parsing_mode,
|
||||
quirks_mode);
|
||||
Parser::new(input).parse_entirely(|parser| {
|
||||
let mut input = ParserInput::new(input);
|
||||
Parser::new(&mut input).parse_entirely(|parser| {
|
||||
PropertyDeclaration::parse_into(declarations, id, &context, parser)
|
||||
.map_err(|_| ())
|
||||
})
|
||||
.map_err(|e| e.into())
|
||||
}).map_err(|_| ())
|
||||
}
|
||||
|
||||
/// A struct to parse property declarations.
|
||||
|
@ -910,23 +913,26 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
|
|||
|
||||
|
||||
/// Default methods reject all at rules.
|
||||
impl<'a, 'b> AtRuleParser for PropertyDeclarationParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type AtRule = Importance;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||
type Declaration = Importance;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Importance, ()> {
|
||||
let id = try!(PropertyId::parse(name.into()));
|
||||
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||
-> Result<Importance, ParseError<'i>> {
|
||||
let id = try!(PropertyId::parse(name));
|
||||
input.parse_until_before(Delimiter::Bang, |input| {
|
||||
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
|
||||
.map_err(|_| ())
|
||||
.map_err(|e| e.into())
|
||||
})?;
|
||||
let importance = match input.try(parse_important) {
|
||||
Ok(()) => Importance::Important,
|
||||
Err(()) => Importance::Normal,
|
||||
Err(_) => Importance::Normal,
|
||||
};
|
||||
// In case there is still unparsed text in the declaration, we should roll back.
|
||||
input.expect_exhausted()?;
|
||||
|
@ -952,12 +958,12 @@ pub fn parse_property_declaration_list(context: &ParserContext,
|
|||
Ok(importance) => {
|
||||
block.extend(iter.parser.declarations.drain(), importance);
|
||||
}
|
||||
Err(range) => {
|
||||
Err(err) => {
|
||||
iter.parser.declarations.clear();
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported property declaration: '{}'",
|
||||
iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, &context);
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::UnsupportedPropertyDeclaration(
|
||||
iter.input.slice(err.span), err.error);
|
||||
log_css_error(iter.input, pos, error, &context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
% endif
|
||||
#[allow(unused_variables)]
|
||||
#[inline]
|
||||
pub fn parse(context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
% if allow_quirks:
|
||||
specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
|
||||
% elif needs_context:
|
||||
|
@ -87,12 +87,16 @@
|
|||
|
||||
pub mod single_value {
|
||||
#[allow(unused_imports)]
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, BasicParseError};
|
||||
#[allow(unused_imports)]
|
||||
use parser::{Parse, ParserContext};
|
||||
#[allow(unused_imports)]
|
||||
use properties::ShorthandId;
|
||||
#[allow(unused_imports)]
|
||||
use selectors::parser::SelectorParseError;
|
||||
#[allow(unused_imports)]
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
#[allow(unused_imports)]
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
#[allow(unused_imports)]
|
||||
use values::{computed, specified};
|
||||
|
@ -207,7 +211,8 @@
|
|||
% endif
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
#[allow(unused_imports)]
|
||||
use parser::parse_space_or_comma_separated;
|
||||
|
||||
|
@ -266,7 +271,7 @@
|
|||
pub mod ${property.ident} {
|
||||
% if not property.derived_from:
|
||||
#[allow(unused_imports)]
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Parser, BasicParseError, Token};
|
||||
#[allow(unused_imports)]
|
||||
use parser::{Parse, ParserContext};
|
||||
#[allow(unused_imports)]
|
||||
|
@ -287,8 +292,12 @@
|
|||
#[allow(unused_imports)]
|
||||
use properties::style_structs;
|
||||
#[allow(unused_imports)]
|
||||
use selectors::parser::SelectorParseError;
|
||||
#[allow(unused_imports)]
|
||||
use stylearc::Arc;
|
||||
#[allow(unused_imports)]
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
#[allow(unused_imports)]
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
#[allow(unused_imports)]
|
||||
use values::{computed, generics, specified};
|
||||
|
@ -423,12 +432,12 @@
|
|||
% endif
|
||||
}
|
||||
% if not property.derived_from:
|
||||
pub fn parse_specified(context: &ParserContext, input: &mut Parser)
|
||||
pub fn parse_specified<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
% if property.boxed:
|
||||
-> Result<Box<SpecifiedValue>, ()> {
|
||||
-> Result<Box<SpecifiedValue>, ParseError<'i>> {
|
||||
parse(context, input).map(|result| Box::new(result))
|
||||
% else:
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
% if property.allow_quirks:
|
||||
parse_quirky(context, input, specified::AllowQuirks::Yes)
|
||||
% else:
|
||||
|
@ -436,11 +445,11 @@
|
|||
% endif
|
||||
% endif
|
||||
}
|
||||
pub fn parse_declared(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<PropertyDeclaration, ()> {
|
||||
pub fn parse_declared<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<PropertyDeclaration, ParseError<'i>> {
|
||||
match input.try(|i| CSSWideKeyword::parse(context, i)) {
|
||||
Ok(keyword) => Ok(PropertyDeclaration::CSSWideKeyword(LonghandId::${property.camel_case}, keyword)),
|
||||
Err(()) => {
|
||||
Err(_) => {
|
||||
input.look_for_var_functions();
|
||||
let start = input.position();
|
||||
let specified = parse_specified(context, input);
|
||||
|
@ -487,7 +496,7 @@
|
|||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
define_css_keyword_enum! { T:
|
||||
% for value in keyword.values_for(product):
|
||||
"${value}" => ${to_rust_ident(value)},
|
||||
|
@ -495,7 +504,7 @@
|
|||
}
|
||||
|
||||
impl Parse for T {
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
T::parse(input)
|
||||
}
|
||||
}
|
||||
|
@ -518,7 +527,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> {
|
||||
Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
|
||||
}
|
||||
|
||||
|
@ -716,14 +725,14 @@
|
|||
SpecifiedValue::${to_rust_ident(values.split()[0])}
|
||||
}
|
||||
#[inline]
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(input)
|
||||
}
|
||||
impl Parse for SpecifiedValue {
|
||||
#[inline]
|
||||
fn parse(_context: &ParserContext, input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(input)
|
||||
}
|
||||
}
|
||||
|
@ -764,9 +773,11 @@
|
|||
use parser::ParserContext;
|
||||
use properties::{PropertyDeclaration, SourcePropertyDeclaration, MaybeBoxed};
|
||||
use properties::{ShorthandId, LonghandId, UnparsedValue, longhands};
|
||||
#[allow(unused_imports)]
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::fmt;
|
||||
use stylearc::Arc;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
|
||||
pub struct Longhands {
|
||||
% for sub_property in shorthand.sub_properties:
|
||||
|
@ -838,8 +849,8 @@
|
|||
|
||||
/// Parse the given shorthand and fill the result into the
|
||||
/// `declarations` vector.
|
||||
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
|
||||
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
|
||||
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
|
||||
context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> {
|
||||
input.look_for_var_functions();
|
||||
let start = input.position();
|
||||
let value = input.parse_entirely(|input| parse_value(context, input));
|
||||
|
@ -872,7 +883,7 @@
|
|||
% endfor
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -890,7 +901,8 @@
|
|||
use values::generics::rect::Rect;
|
||||
use values::specified;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let rect = Rect::parse_with(context, input, |_c, i| {
|
||||
% if allow_quirks:
|
||||
${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
|
||||
|
@ -1114,7 +1126,8 @@
|
|||
use values::computed::${length_type};
|
||||
${length_type}::${initial_value}
|
||||
}
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
% if logical:
|
||||
let ret = ${length_type}::parse(context, input);
|
||||
% else:
|
||||
|
@ -1123,7 +1136,7 @@
|
|||
// Keyword values don't make sense in the block direction; don't parse them
|
||||
% if "block" in name:
|
||||
if let Ok(${length_type}::ExtremumLength(..)) = ret {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
% endif
|
||||
ret.map(SpecifiedValue)
|
||||
|
|
|
@ -27,12 +27,13 @@ use properties::longhands::transform::computed_value::T as TransformList;
|
|||
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
|
||||
use properties::longhands::visibility::computed_value::T as Visibility;
|
||||
#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
|
||||
use selectors::parser::SelectorParseError;
|
||||
#[cfg(feature = "servo")] use servo_atoms::Atom;
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp;
|
||||
#[cfg(feature = "gecko")] use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
use super::ComputedValues;
|
||||
use values::CSSFloat;
|
||||
use values::{Auto, Either};
|
||||
|
@ -99,9 +100,9 @@ impl TransitionProperty {
|
|||
}
|
||||
|
||||
/// Parse a transition-property value.
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let ident = try!(input.expect_ident());
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"all" => Ok(TransitionProperty::All),
|
||||
% for prop in data.longhands:
|
||||
% if prop.animatable:
|
||||
|
@ -118,7 +119,7 @@ impl TransitionProperty {
|
|||
None => Ok(TransitionProperty::Unsupported((&*ident).into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
|
||||
}
|
||||
|
||||
/// Get a transition property from a property declaration.
|
||||
|
@ -476,7 +477,7 @@ impl AnimationValue {
|
|||
/// Construct an AnimationValue from a property declaration
|
||||
pub fn from_declaration(decl: &PropertyDeclaration, context: &mut Context,
|
||||
initial: &ComputedValues) -> Option<Self> {
|
||||
use error_reporting::RustLogReporter;
|
||||
use error_reporting::create_error_reporter;
|
||||
use properties::LonghandId;
|
||||
use properties::DeclaredValue;
|
||||
|
||||
|
@ -539,7 +540,7 @@ impl AnimationValue {
|
|||
},
|
||||
PropertyDeclaration::WithVariables(id, ref variables) => {
|
||||
let custom_props = context.style().custom_properties();
|
||||
let reporter = RustLogReporter;
|
||||
let reporter = create_error_reporter();
|
||||
match id {
|
||||
% for prop in data.longhands:
|
||||
% if prop.animatable:
|
||||
|
|
|
@ -128,17 +128,20 @@ ${helpers.predefined_type("background-image", "ImageLayer",
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"repeat-x" => Ok(SpecifiedValue::RepeatX),
|
||||
"repeat-y" => Ok(SpecifiedValue::RepeatY),
|
||||
_ => {
|
||||
let horizontal = try!(RepeatKeyword::from_ident(&ident));
|
||||
let vertical = input.try(RepeatKeyword::parse).ok();
|
||||
Ok(SpecifiedValue::Other(horizontal, vertical))
|
||||
}
|
||||
}
|
||||
_ => Err(()),
|
||||
}).or_else(|()| {
|
||||
let horizontal: Result<_, ParseError> = RepeatKeyword::from_ident(&ident)
|
||||
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
|
||||
let horizontal = try!(horizontal);
|
||||
let vertical = input.try(RepeatKeyword::parse).ok();
|
||||
Ok(SpecifiedValue::Other(horizontal, vertical))
|
||||
})
|
||||
}
|
||||
</%helpers:vector_longhand>
|
||||
|
||||
|
|
|
@ -161,8 +161,8 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue::None)
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
|
|||
if !result.is_empty() {
|
||||
Ok(SpecifiedValue::Colors(result))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
@ -272,7 +272,8 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let first = try!(RepeatKeyword::parse(input));
|
||||
let second = input.try(RepeatKeyword::parse).ok();
|
||||
|
||||
|
|
|
@ -113,16 +113,17 @@
|
|||
}
|
||||
|
||||
/// Parse a display value.
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let ident = try!(input.expect_ident());
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
% for value in values:
|
||||
"${value}" => {
|
||||
Ok(computed_value::T::${to_rust_ident(value)})
|
||||
},
|
||||
% endfor
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
|
@ -292,16 +293,18 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
|
|||
}
|
||||
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
||||
/// | <percentage> | <length>
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes))
|
||||
.map(SpecifiedValue::LengthOrPercentage)
|
||||
.or_else(|_| {
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
let ident = try!(input.expect_ident());
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
% for keyword in vertical_align_keywords:
|
||||
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
|
||||
% endfor
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -500,17 +503,19 @@ ${helpers.predefined_type("transition-delay",
|
|||
}
|
||||
|
||||
impl Parse for SpecifiedValue {
|
||||
fn parse(context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(name) = input.try(|input| KeyframesName::parse(context, input)) {
|
||||
Ok(SpecifiedValue(Some(name)))
|
||||
} else {
|
||||
input.expect_ident_matching("none").map(|()| SpecifiedValue(None))
|
||||
input.expect_ident_matching("none").map(|_| SpecifiedValue(None)).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
SpecifiedValue::parse(context, input)
|
||||
}
|
||||
|
||||
|
@ -560,14 +565,15 @@ ${helpers.predefined_type("animation-timing-function",
|
|||
}
|
||||
|
||||
impl Parse for SpecifiedValue {
|
||||
fn parse(_context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
|
||||
return Ok(SpecifiedValue::Infinite)
|
||||
}
|
||||
|
||||
let number = try!(input.expect_number());
|
||||
if number < 0.0 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(SpecifiedValue::Number(number))
|
||||
|
@ -587,7 +593,8 @@ ${helpers.predefined_type("animation-timing-function",
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(context, input)
|
||||
}
|
||||
|
||||
|
@ -948,8 +955,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
}
|
||||
|
||||
// Allow unitless zero angle for rotate() and skew() to align with gecko
|
||||
fn parse_internal(context: &ParserContext, input: &mut Parser, prefixed: bool)
|
||||
-> Result<SpecifiedValue,()> {
|
||||
fn parse_internal<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, prefixed: bool)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue(Vec::new()))
|
||||
}
|
||||
|
@ -960,7 +967,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
Ok(name) => name,
|
||||
Err(_) => break,
|
||||
};
|
||||
match_ignore_ascii_case! {
|
||||
let valid_fn = match_ignore_ascii_case! {
|
||||
&name,
|
||||
"matrix" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
|
@ -970,7 +977,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
specified::parse_number(context, input)
|
||||
}));
|
||||
if values.len() != 6 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
result.push(SpecifiedOperation::Matrix {
|
||||
|
@ -981,7 +988,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
e: values[4],
|
||||
f: values[5],
|
||||
});
|
||||
return Ok(());
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Non-standard prefixed matrix parsing.
|
||||
|
@ -1014,7 +1021,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
e: lengths[0].clone(),
|
||||
f: lengths[1].clone(),
|
||||
});
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"matrix3d" => {
|
||||
|
@ -1023,7 +1030,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
if !prefixed {
|
||||
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
|
||||
if values.len() != 16 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
result.push(SpecifiedOperation::Matrix3D {
|
||||
|
@ -1032,7 +1039,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
|
||||
m41: values[12], m42: values[13], m43: values[14], m44: values[15]
|
||||
});
|
||||
return Ok(());
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Non-standard prefixed matrix3d parsing.
|
||||
|
@ -1069,7 +1076,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
|
||||
m44: values[12]
|
||||
});
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"translate" => {
|
||||
|
@ -1081,28 +1088,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
} else {
|
||||
result.push(SpecifiedOperation::Translate(sx, None));
|
||||
}
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"translatex" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let tx = try!(specified::LengthOrPercentage::parse(context, input));
|
||||
result.push(SpecifiedOperation::TranslateX(tx));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"translatey" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let ty = try!(specified::LengthOrPercentage::parse(context, input));
|
||||
result.push(SpecifiedOperation::TranslateY(ty));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"translatez" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let tz = try!(specified::Length::parse(context, input));
|
||||
result.push(SpecifiedOperation::TranslateZ(tz));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"translate3d" => {
|
||||
|
@ -1113,7 +1120,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
try!(input.expect_comma());
|
||||
let tz = try!(specified::Length::parse(context, input));
|
||||
result.push(SpecifiedOperation::Translate3D(tx, ty, tz));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"scale" => {
|
||||
|
@ -1125,28 +1132,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
} else {
|
||||
result.push(SpecifiedOperation::Scale(sx, None));
|
||||
}
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"scalex" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let sx = try!(specified::parse_number(context, input));
|
||||
result.push(SpecifiedOperation::ScaleX(sx));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"scaley" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let sy = try!(specified::parse_number(context, input));
|
||||
result.push(SpecifiedOperation::ScaleY(sy));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"scalez" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let sz = try!(specified::parse_number(context, input));
|
||||
result.push(SpecifiedOperation::ScaleZ(sz));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"scale3d" => {
|
||||
|
@ -1157,35 +1164,35 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
try!(input.expect_comma());
|
||||
let sz = try!(specified::parse_number(context, input));
|
||||
result.push(SpecifiedOperation::Scale3D(sx, sy, sz));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"rotate" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
result.push(SpecifiedOperation::Rotate(theta));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"rotatex" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
result.push(SpecifiedOperation::RotateX(theta));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"rotatey" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
result.push(SpecifiedOperation::RotateY(theta));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"rotatez" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
result.push(SpecifiedOperation::RotateZ(theta));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"rotate3d" => {
|
||||
|
@ -1199,7 +1206,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
// TODO(gw): Check the axis can be normalized!!
|
||||
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"skew" => {
|
||||
|
@ -1211,51 +1218,56 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
} else {
|
||||
result.push(SpecifiedOperation::Skew(theta_x, None));
|
||||
}
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"skewx" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta_x = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
result.push(SpecifiedOperation::SkewX(theta_x));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"skewy" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta_y = try!(specified::Angle::parse_with_unitless(context, input));
|
||||
result.push(SpecifiedOperation::SkewY(theta_y));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
"perspective" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let d = try!(specified::Length::parse_non_negative(context, input));
|
||||
result.push(SpecifiedOperation::Perspective(d));
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}))
|
||||
},
|
||||
_ => return Err(())
|
||||
_ => false
|
||||
};
|
||||
if !valid_fn {
|
||||
return Err(StyleParseError::UnexpectedFunction(name).into());
|
||||
}
|
||||
}
|
||||
|
||||
if !result.is_empty() {
|
||||
Ok(SpecifiedValue(result))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses `transform` property.
|
||||
#[inline]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
parse_internal(context, input, false)
|
||||
}
|
||||
|
||||
/// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
|
||||
/// in the nondiagonal homogeneous components of matrix and matrix3d.
|
||||
#[inline]
|
||||
pub fn parse_prefixed(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse_prefixed<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
parse_internal(context, input, true)
|
||||
}
|
||||
|
||||
|
@ -1771,7 +1783,8 @@ ${helpers.predefined_type("transform-origin",
|
|||
}
|
||||
|
||||
/// none | strict | content | [ size || layout || style || paint ]
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = SpecifiedValue::empty();
|
||||
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
|
@ -1784,21 +1797,22 @@ ${helpers.predefined_type("transform-origin",
|
|||
|
||||
while let Ok(name) = input.try(|input| input.expect_ident()) {
|
||||
let flag = match_ignore_ascii_case! { &name,
|
||||
"layout" => LAYOUT,
|
||||
"style" => STYLE,
|
||||
"paint" => PAINT,
|
||||
_ => return Err(())
|
||||
"layout" => Some(LAYOUT),
|
||||
"style" => Some(STYLE),
|
||||
"paint" => Some(PAINT),
|
||||
_ => None
|
||||
};
|
||||
let flag = match flag {
|
||||
Some(flag) if !result.contains(flag) => flag,
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name).into())
|
||||
};
|
||||
if result.contains(flag) {
|
||||
return Err(())
|
||||
}
|
||||
result.insert(flag);
|
||||
}
|
||||
|
||||
if !result.is_empty() {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
@ -1900,18 +1914,23 @@ ${helpers.single_keyword("-moz-orient",
|
|||
}
|
||||
|
||||
/// auto | <animateable-feature>#
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||
Ok(computed_value::T::Auto)
|
||||
} else {
|
||||
input.parse_comma_separated(|i| {
|
||||
let ident = i.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
let bad_keyword = match_ignore_ascii_case! { &ident,
|
||||
"will-change" | "none" | "all" | "auto" |
|
||||
"initial" | "inherit" | "unset" | "default" => return Err(()),
|
||||
_ => {},
|
||||
"initial" | "inherit" | "unset" | "default" => true,
|
||||
_ => false,
|
||||
};
|
||||
if bad_keyword {
|
||||
Err(SelectorParseError::UnexpectedIdent(ident.into()).into())
|
||||
} else {
|
||||
Ok(Atom::from(ident))
|
||||
}
|
||||
Ok((Atom::from(ident)))
|
||||
}).map(SpecifiedValue::AnimateableFeatures)
|
||||
}
|
||||
}
|
||||
|
@ -1976,9 +1995,10 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
|
|||
TOUCH_ACTION_AUTO
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"auto" => Ok(TOUCH_ACTION_AUTO),
|
||||
"none" => Ok(TOUCH_ACTION_NONE),
|
||||
"manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
|
||||
|
@ -1997,7 +2017,7 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
|
|||
}
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
pub fn get_initial_value() -> computed_value::T {
|
||||
RGBA::new(0, 0, 0, 255) // black
|
||||
}
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
|
||||
}
|
||||
|
||||
|
@ -118,7 +119,7 @@
|
|||
}
|
||||
|
||||
impl SystemColor {
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
#[cfg(feature = "gecko")]
|
||||
use std::ascii::AsciiExt;
|
||||
static PARSE_ARRAY: &'static [(&'static str, SystemColor); ${len(system_colors)}] = &[
|
||||
|
@ -133,7 +134,7 @@
|
|||
return Ok(color)
|
||||
}
|
||||
}
|
||||
Err(())
|
||||
Err(SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
% endif
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
<%helpers:longhand name="content" boxed="True" animation_value_type="none"
|
||||
spec="https://drafts.csswg.org/css-content/#propdef-content">
|
||||
use cssparser::Token;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::generics::CounterStyleOrNone;
|
||||
|
@ -157,8 +156,8 @@
|
|||
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
|
||||
// no-close-quote ]+
|
||||
// TODO: <uri>, attr(<identifier>)
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(SpecifiedValue::Normal)
|
||||
}
|
||||
|
@ -185,43 +184,50 @@
|
|||
content.push(ContentItem::String(value.into_owned()))
|
||||
}
|
||||
Ok(Token::Function(name)) => {
|
||||
content.push(try!(match_ignore_ascii_case! { &name,
|
||||
"counter" => input.parse_nested_block(|input| {
|
||||
let result = match_ignore_ascii_case! { &name,
|
||||
"counter" => Some(input.parse_nested_block(|input| {
|
||||
let name = try!(input.expect_ident()).into_owned();
|
||||
let style = parse_counter_style(context, input);
|
||||
Ok(ContentItem::Counter(name, style))
|
||||
}),
|
||||
"counters" => input.parse_nested_block(|input| {
|
||||
})),
|
||||
"counters" => Some(input.parse_nested_block(|input| {
|
||||
let name = try!(input.expect_ident()).into_owned();
|
||||
try!(input.expect_comma());
|
||||
let separator = try!(input.expect_string()).into_owned();
|
||||
let style = parse_counter_style(context, input);
|
||||
Ok(ContentItem::Counters(name, separator, style))
|
||||
}),
|
||||
})),
|
||||
% if product == "gecko":
|
||||
"attr" => input.parse_nested_block(|input| {
|
||||
"attr" => Some(input.parse_nested_block(|input| {
|
||||
Ok(ContentItem::Attr(Attr::parse_function(context, input)?))
|
||||
}),
|
||||
})),
|
||||
% endif
|
||||
_ => return Err(())
|
||||
}));
|
||||
_ => None
|
||||
};
|
||||
match result {
|
||||
Some(result) => content.push(try!(result)),
|
||||
None => return Err(StyleParseError::UnexpectedFunction(name).into())
|
||||
}
|
||||
}
|
||||
Ok(Token::Ident(ident)) => {
|
||||
match_ignore_ascii_case! { &ident,
|
||||
"open-quote" => content.push(ContentItem::OpenQuote),
|
||||
"close-quote" => content.push(ContentItem::CloseQuote),
|
||||
"no-open-quote" => content.push(ContentItem::NoOpenQuote),
|
||||
"no-close-quote" => content.push(ContentItem::NoCloseQuote),
|
||||
let valid = match_ignore_ascii_case! { &ident,
|
||||
"open-quote" => { content.push(ContentItem::OpenQuote); true },
|
||||
"close-quote" => { content.push(ContentItem::CloseQuote); true },
|
||||
"no-open-quote" => { content.push(ContentItem::NoOpenQuote); true },
|
||||
"no-close-quote" => { content.push(ContentItem::NoCloseQuote); true },
|
||||
|
||||
_ => return Err(())
|
||||
_ => false,
|
||||
};
|
||||
if !valid {
|
||||
return Err(SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
Err(_) => break,
|
||||
_ => return Err(())
|
||||
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into())
|
||||
}
|
||||
}
|
||||
if content.is_empty() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
Ok(SpecifiedValue::Items(content))
|
||||
}
|
||||
|
@ -233,8 +239,6 @@
|
|||
use style_traits::ToCss;
|
||||
use values::CustomIdent;
|
||||
|
||||
use cssparser::Token;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct SpecifiedValue(pub Vec<(CustomIdent, specified::Integer)>);
|
||||
|
||||
|
@ -315,11 +319,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
parse_common(context, 1, input)
|
||||
}
|
||||
|
||||
pub fn parse_common(context: &ParserContext, default_value: i32, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse_common<'i, 't>(context: &ParserContext, default_value: i32, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue(Vec::new()))
|
||||
}
|
||||
|
@ -328,7 +334,7 @@
|
|||
loop {
|
||||
let counter_name = match input.next() {
|
||||
Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?,
|
||||
Ok(_) => return Err(()),
|
||||
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(_) => break,
|
||||
};
|
||||
let counter_delta = input.try(|input| specified::parse_integer(context, input))
|
||||
|
@ -339,7 +345,7 @@
|
|||
if !counters.is_empty() {
|
||||
Ok(SpecifiedValue(counters))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
@ -349,7 +355,8 @@
|
|||
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
|
||||
use super::counter_increment::parse_common;
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
parse_common(context, 0, input)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
|
|
@ -27,7 +27,8 @@ ${helpers.predefined_type("opacity",
|
|||
pub type T = Shadow;
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<specified::Shadow, ParseError<'i>> {
|
||||
specified::Shadow::parse(context, input, false)
|
||||
}
|
||||
</%helpers:vector_longhand>
|
||||
|
@ -263,7 +264,8 @@ ${helpers.predefined_type("clip",
|
|||
computed_value::T::new(Vec::new())
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut filters = Vec::new();
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue(filters))
|
||||
|
@ -290,23 +292,24 @@ ${helpers.predefined_type("clip",
|
|||
"drop-shadow" => specified::Shadow::parse(context, input, true)
|
||||
.map(SpecifiedFilter::DropShadow),
|
||||
% endif
|
||||
_ => Err(())
|
||||
_ => Err(StyleParseError::UnexpectedFunction(function_name.clone()).into())
|
||||
}
|
||||
})));
|
||||
} else if filters.is_empty() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
return Ok(SpecifiedValue(filters))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_factor(input: &mut Parser) -> Result<::values::CSSFloat, ()> {
|
||||
fn parse_factor<'i, 't>(input: &mut Parser<'i, 't>) -> Result<::values::CSSFloat, ParseError<'i>> {
|
||||
use cssparser::Token;
|
||||
match input.next() {
|
||||
Ok(Token::Number(value)) if value.value.is_sign_positive() => Ok(value.value),
|
||||
Ok(Token::Percentage(value)) if value.unit_value.is_sign_positive() => Ok(value.unit_value),
|
||||
_ => Err(())
|
||||
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => Err(e.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ macro_rules! impl_gecko_keyword_from_trait {
|
|||
use cssparser::{CssStringWriter, Parser, serialize_identifier};
|
||||
use std::fmt::{self, Write};
|
||||
use Atom;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
pub use self::FontFamily as SingleComputedValue;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
|
@ -154,7 +154,7 @@ macro_rules! impl_gecko_keyword_from_trait {
|
|||
}
|
||||
|
||||
/// Parse a font-family value
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(value) = input.try(|input| input.expect_string()) {
|
||||
return Ok(FontFamily::FamilyName(FamilyName {
|
||||
name: Atom::from(&*value),
|
||||
|
@ -294,7 +294,8 @@ macro_rules! impl_gecko_keyword_from_trait {
|
|||
/// <family-name>#
|
||||
/// <family-name> = <string> | [ <ident>+ ]
|
||||
/// TODO: <generic-family>
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(input)
|
||||
}
|
||||
|
||||
|
@ -348,7 +349,7 @@ macro_rules! impl_gecko_keyword_from_trait {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue::Values)
|
||||
}
|
||||
}
|
||||
|
@ -374,11 +375,11 @@ macro_rules! impl_gecko_keyword_from_trait {
|
|||
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
|
||||
/// because we want the former to exclude generic family keywords.
|
||||
impl Parse for FamilyName {
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
match FontFamily::parse(input) {
|
||||
Ok(FontFamily::FamilyName(name)) => Ok(name),
|
||||
Ok(FontFamily::Generic(_)) |
|
||||
Err(()) => Err(())
|
||||
Ok(FontFamily::Generic(_)) => Err(StyleParseError::UnspecifiedError.into()),
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -444,17 +445,21 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
}
|
||||
|
||||
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
input.try(|input| {
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let result: Result<_, ParseError> = input.try(|input| {
|
||||
let ident = try!(input.expect_ident());
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"normal" => Ok(SpecifiedValue::Normal),
|
||||
"bold" => Ok(SpecifiedValue::Bold),
|
||||
"bolder" => Ok(SpecifiedValue::Bolder),
|
||||
"lighter" => Ok(SpecifiedValue::Lighter),
|
||||
_ => Err(())
|
||||
}
|
||||
}).or_else(|()| {
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
});
|
||||
result.or_else(|_| {
|
||||
SpecifiedValue::from_int(input.expect_integer()?)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -489,7 +494,7 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
|
||||
/// Used in @font-face, where relative keywords are not allowed.
|
||||
impl Parse for computed_value::T {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
match parse(context, input)? {
|
||||
% for weight in range(100, 901, 100):
|
||||
SpecifiedValue::Weight${weight} => Ok(computed_value::T::Weight${weight}),
|
||||
|
@ -497,7 +502,7 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
|
||||
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
|
||||
SpecifiedValue::Bolder |
|
||||
SpecifiedValue::Lighter => Err(()),
|
||||
SpecifiedValue::Lighter => Err(StyleParseError::UnspecifiedError.into()),
|
||||
SpecifiedValue::System(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -683,17 +688,18 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
pub use self::KeywordSize::*;
|
||||
|
||||
impl KeywordSize {
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
Ok(match_ignore_ascii_case! {&*input.expect_ident()?,
|
||||
"xx-small" => XXSmall,
|
||||
"x-small" => XSmall,
|
||||
"small" => Small,
|
||||
"medium" => Medium,
|
||||
"large" => Large,
|
||||
"x-large" => XLarge,
|
||||
"xx-large" => XXLarge,
|
||||
_ => return Err(())
|
||||
})
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! {&*ident,
|
||||
"xx-small" => Ok(XXSmall),
|
||||
"x-small" => Ok(XSmall),
|
||||
"small" => Ok(Small),
|
||||
"medium" => Ok(Medium),
|
||||
"large" => Ok(Large),
|
||||
"x-large" => Ok(XLarge),
|
||||
"xx-large" => Ok(XXLarge),
|
||||
_ => Err(())
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -906,15 +912,16 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
}
|
||||
|
||||
/// <length> | <percentage> | <absolute-size> | <relative-size>
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
|
||||
/// Parses a font-size, with quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
use self::specified::LengthOrPercentage;
|
||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) {
|
||||
return Ok(SpecifiedValue::Length(lop))
|
||||
|
@ -924,11 +931,12 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
return Ok(SpecifiedValue::Keyword(kw, 1.))
|
||||
}
|
||||
|
||||
match_ignore_ascii_case! {&*input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! {&*ident,
|
||||
"smaller" => Ok(SpecifiedValue::Smaller),
|
||||
"larger" => Ok(SpecifiedValue::Larger),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
impl SpecifiedValue {
|
||||
|
@ -1150,7 +1158,8 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
}
|
||||
|
||||
/// none | <number>
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
use values::specified::Number;
|
||||
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
|
@ -1200,9 +1209,11 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
SpecifiedValue { weight: true, style: true }
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = SpecifiedValue { weight: false, style: false };
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
let ident = try!(input.expect_ident());
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"none" => Ok(result),
|
||||
"weight" => {
|
||||
result.weight = true;
|
||||
|
@ -1219,7 +1230,7 @@ ${helpers.single_keyword_system("font-variant-caps",
|
|||
Ok(result)
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -1364,7 +1375,8 @@ ${helpers.single_keyword_system("font-kerning",
|
|||
/// swash(<feature-value-name>) ||
|
||||
/// ornaments(<feature-value-name>) ||
|
||||
/// annotation(<feature-value-name>) ]
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = VariantAlternates::empty();
|
||||
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
|
@ -1373,25 +1385,26 @@ ${helpers.single_keyword_system("font-kerning",
|
|||
|
||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||
let flag = match_ignore_ascii_case! { &ident,
|
||||
"stylistic" => STYLISTIC,
|
||||
"historical-forms" => HISTORICAL_FORMS,
|
||||
"styleset" => STYLESET,
|
||||
"character-variant" => CHARACTER_VARIANT,
|
||||
"swash" => SWASH,
|
||||
"ornaments" => ORNAMENTS,
|
||||
"annotation" => ANNOTATION,
|
||||
_ => return Err(()),
|
||||
"stylistic" => Some(STYLISTIC),
|
||||
"historical-forms" => Some(HISTORICAL_FORMS),
|
||||
"styleset" => Some(STYLESET),
|
||||
"character-variant" => Some(CHARACTER_VARIANT),
|
||||
"swash" => Some(SWASH),
|
||||
"ornaments" => Some(ORNAMENTS),
|
||||
"annotation" => Some(ANNOTATION),
|
||||
_ => None,
|
||||
};
|
||||
let flag = match flag {
|
||||
Some(flag) if !result.intersects(flag) => flag,
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||
};
|
||||
if result.intersects(flag) {
|
||||
return Err(())
|
||||
}
|
||||
result.insert(flag);
|
||||
}
|
||||
|
||||
if !result.is_empty() {
|
||||
Ok(SpecifiedValue::Value(result))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
@ -1400,9 +1413,9 @@ ${helpers.single_keyword_system("font-kerning",
|
|||
macro_rules! exclusive_value {
|
||||
(($value:ident, $set:expr) => $ident:ident) => {
|
||||
if $value.intersects($set) {
|
||||
return Err(())
|
||||
None
|
||||
} else {
|
||||
$ident
|
||||
Some($ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1507,7 +1520,8 @@ macro_rules! exclusive_value {
|
|||
/// <east-asian-width-values> = [ full-width | proportional-width ]
|
||||
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
|
||||
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = VariantEastAsian::empty();
|
||||
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
|
@ -1534,7 +1548,11 @@ macro_rules! exclusive_value {
|
|||
exclusive_value!((result, ${east_asian_width_values}) => PROPORTIONAL_WIDTH),
|
||||
"ruby" =>
|
||||
exclusive_value!((result, RUBY) => RUBY),
|
||||
_ => return Err(()),
|
||||
_ => None,
|
||||
};
|
||||
let flag = match flag {
|
||||
Some(flag) => flag,
|
||||
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||
};
|
||||
result.insert(flag);
|
||||
}
|
||||
|
@ -1542,7 +1560,7 @@ macro_rules! exclusive_value {
|
|||
if !result.is_empty() {
|
||||
Ok(SpecifiedValue::Value(result))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1659,7 +1677,8 @@ macro_rules! exclusive_value {
|
|||
<% discretionary_lig_values = "DISCRETIONARY_LIGATURES | NO_DISCRETIONARY_LIGATURES" %>
|
||||
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
|
||||
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = VariantLigatures::empty();
|
||||
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
|
@ -1687,7 +1706,11 @@ macro_rules! exclusive_value {
|
|||
exclusive_value!((result, ${contextual_alt_values}) => CONTEXTUAL),
|
||||
"no-contextual" =>
|
||||
exclusive_value!((result, ${contextual_alt_values}) => NO_CONTEXTUAL),
|
||||
_ => return Err(()),
|
||||
_ => None,
|
||||
};
|
||||
let flag = match flag {
|
||||
Some(flag) => flag,
|
||||
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||
};
|
||||
result.insert(flag);
|
||||
}
|
||||
|
@ -1695,7 +1718,7 @@ macro_rules! exclusive_value {
|
|||
if !result.is_empty() {
|
||||
Ok(SpecifiedValue::Value(result))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1808,7 +1831,8 @@ macro_rules! exclusive_value {
|
|||
<% numeric_figure_values = "LINING_NUMS | OLDSTYLE_NUMS" %>
|
||||
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
|
||||
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = VariantNumeric::empty();
|
||||
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
|
@ -1824,16 +1848,20 @@ macro_rules! exclusive_value {
|
|||
"lining-nums" =>
|
||||
exclusive_value!((result, ${numeric_figure_values}) => LINING_NUMS ),
|
||||
"oldstyle-nums" =>
|
||||
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS ),
|
||||
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS),
|
||||
"proportional-nums" =>
|
||||
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS ),
|
||||
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS),
|
||||
"tabular-nums" =>
|
||||
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS ),
|
||||
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS),
|
||||
"diagonal-fractions" =>
|
||||
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS ),
|
||||
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS),
|
||||
"stacked-fractions" =>
|
||||
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS ),
|
||||
_ => return Err(()),
|
||||
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS),
|
||||
_ => None,
|
||||
};
|
||||
let flag = match flag {
|
||||
Some(flag) => flag,
|
||||
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||
};
|
||||
result.insert(flag);
|
||||
}
|
||||
|
@ -1841,7 +1869,7 @@ macro_rules! exclusive_value {
|
|||
if !result.is_empty() {
|
||||
Ok(SpecifiedValue::Value(result))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1890,7 +1918,8 @@ ${helpers.single_keyword_system("font-variant-position",
|
|||
}
|
||||
|
||||
/// normal | <feature-tag-value>#
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
computed_value::T::parse(context, input).map(SpecifiedValue::Value)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
@ -1924,7 +1953,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
|||
}
|
||||
|
||||
/// normal | <feature-tag-value>#
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
computed_value::T::parse(context, input)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
@ -2054,13 +2084,14 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
|||
}
|
||||
|
||||
/// normal | <string>
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
Ok(SpecifiedValue::Normal)
|
||||
} else {
|
||||
input.expect_string().map(|cow| {
|
||||
SpecifiedValue::Override(cow.into_owned())
|
||||
})
|
||||
}).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2108,9 +2139,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
|||
computed_value::T(atom!(""))
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
|
@ -2133,9 +2165,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
|||
::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
|
@ -2206,7 +2239,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if let Ok(i) = input.try(|i| i.expect_integer()) {
|
||||
return Ok(SpecifiedValue::Relative(i))
|
||||
}
|
||||
|
@ -2281,9 +2315,10 @@ ${helpers.single_keyword("-moz-math-variant",
|
|||
Au((NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * AU_PER_PT) as i32)
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
|
@ -2308,7 +2343,9 @@ ${helpers.single_keyword("-moz-math-variant",
|
|||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use properties::longhands;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use style_traits::ParseError;
|
||||
use values::computed::{ToComputedValue, Context};
|
||||
<%
|
||||
system_fonts = """caption icon menu message-box small-caption status-bar
|
||||
|
@ -2427,13 +2464,14 @@ ${helpers.single_keyword("-moz-math-variant",
|
|||
}
|
||||
|
||||
impl SystemFont {
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
Ok(match_ignore_ascii_case! { &*input.expect_ident()?,
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &*ident,
|
||||
% for font in system_fonts:
|
||||
"${font}" => SystemFont::${to_camel_case(font)},
|
||||
"${font}" => Ok(SystemFont::${to_camel_case(font)}),
|
||||
% endfor
|
||||
_ => return Err(())
|
||||
})
|
||||
_ => Err(())
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,8 @@ ${helpers.single_keyword("image-rendering",
|
|||
}
|
||||
|
||||
// from-image | <angle> | [<angle>? flip]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
|
||||
// Handle from-image
|
||||
Ok(SpecifiedValue { angle: None, flipped: false })
|
||||
|
@ -185,7 +186,7 @@ ${helpers.single_keyword("image-rendering",
|
|||
// Handle <angle> | <angle> flip
|
||||
let angle = input.try(|input| Angle::parse(context, input)).ok();
|
||||
if angle.is_none() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
|
||||
|
|
|
@ -183,7 +183,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) {
|
||||
Ok(SpecifiedValue(0))
|
||||
} else {
|
||||
|
@ -195,33 +196,34 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
|||
|
||||
loop {
|
||||
|
||||
let result = input.try(|i| {
|
||||
match_ignore_ascii_case! { &i.expect_ident()?,
|
||||
let result: Result<_, ParseError> = input.try(|i| {
|
||||
let ident = i.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"fill" => Ok(FILL),
|
||||
"stroke" => Ok(STROKE),
|
||||
"markers" => Ok(MARKERS),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(val) => {
|
||||
if (seen & (1 << val)) != 0 {
|
||||
// don't parse the same ident twice
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
value |= val << (pos * SHIFT);
|
||||
seen |= 1 << val;
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
Err(()) => break,
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
|
||||
if value == 0 {
|
||||
// couldn't find any keyword
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
// fill in rest
|
||||
for i in pos..COUNT {
|
||||
|
@ -285,7 +287,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
|||
}
|
||||
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let i = input.expect_ident()?;
|
||||
CustomIdent::from_ident(i, &["all", "none", "auto"])
|
||||
}
|
||||
|
|
|
@ -113,11 +113,12 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
let mut first = None;
|
||||
let mut second = None;
|
||||
match Length::parse_non_negative_quirky(context, input, AllowQuirks::Yes) {
|
||||
Err(()) => (),
|
||||
Err(_) => (),
|
||||
Ok(length) => {
|
||||
first = Some(length);
|
||||
if let Ok(len) = input.try(|i| Length::parse_non_negative_quirky(context, i, AllowQuirks::Yes)) {
|
||||
|
@ -126,7 +127,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
}
|
||||
}
|
||||
match (first, second) {
|
||||
(None, None) => Err(()),
|
||||
(None, None) => Err(StyleParseError::UnspecifiedError.into()),
|
||||
(Some(length), None) => {
|
||||
Ok(SpecifiedValue {
|
||||
horizontal: length,
|
||||
|
|
|
@ -179,7 +179,8 @@ ${helpers.single_keyword("text-align-last",
|
|||
MatchParent,
|
||||
MozCenterOrInherit,
|
||||
}
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
// MozCenterOrInherit cannot be parsed, only set directly on th elements
|
||||
if let Ok(key) = input.try(computed_value::T::parse) {
|
||||
Ok(SpecifiedValue::Keyword(key))
|
||||
|
@ -255,7 +256,8 @@ ${helpers.single_keyword("text-align-last",
|
|||
use values::computed::ComputedValueAsSpecified;
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
computed_value::T::parse(input)
|
||||
}
|
||||
% endif
|
||||
|
@ -415,7 +417,8 @@ ${helpers.predefined_type("word-spacing",
|
|||
pub type T = Shadow;
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<specified::Shadow, ParseError<'i>> {
|
||||
specified::Shadow::parse(context, input, true)
|
||||
}
|
||||
</%helpers:vector_longhand>
|
||||
|
@ -577,7 +580,8 @@ ${helpers.predefined_type("word-spacing",
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue::None);
|
||||
}
|
||||
|
@ -603,7 +607,7 @@ ${helpers.predefined_type("word-spacing",
|
|||
(Some(fill), Ok(shape)) => KeywordValue::FillAndShape(fill,shape),
|
||||
(Some(fill), Err(_)) => KeywordValue::Fill(fill),
|
||||
(None, Ok(shape)) => KeywordValue::Shape(shape),
|
||||
_ => return Err(()),
|
||||
_ => return Err(StyleParseError::UnspecifiedError.into()),
|
||||
};
|
||||
Ok(SpecifiedValue::Keyword(keyword_value))
|
||||
}
|
||||
|
@ -636,7 +640,8 @@ ${helpers.predefined_type("word-spacing",
|
|||
SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right)
|
||||
}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
if let Ok(horizontal) = input.try(|input| HorizontalWritingModeValue::parse(input)) {
|
||||
let vertical = try!(VerticalWritingModeValue::parse(input));
|
||||
Ok(SpecifiedValue(horizontal, vertical))
|
||||
|
|
|
@ -89,7 +89,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
|||
SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
|
||||
SpecifiedValue::CounterStyle(style)
|
||||
} else {
|
||||
|
@ -126,7 +127,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
|||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue(Either::Second(None_))
|
||||
}
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
% if product == "gecko":
|
||||
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
|
||||
if let Either::First(ref mut url) = value {
|
||||
|
@ -142,7 +144,6 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
|||
|
||||
<%helpers:longhand name="quotes" animation_value_type="none"
|
||||
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
|
||||
use cssparser::Token;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
@ -187,7 +188,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
|||
])
|
||||
}
|
||||
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue(Vec::new()))
|
||||
}
|
||||
|
@ -196,19 +198,20 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
|||
loop {
|
||||
let first = match input.next() {
|
||||
Ok(Token::QuotedString(value)) => value.into_owned(),
|
||||
Ok(_) => return Err(()),
|
||||
Err(()) => break,
|
||||
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(_) => break,
|
||||
};
|
||||
let second = match input.next() {
|
||||
Ok(Token::QuotedString(value)) => value.into_owned(),
|
||||
_ => return Err(()),
|
||||
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
quotes.push((first, second))
|
||||
}
|
||||
if !quotes.is_empty() {
|
||||
Ok(SpecifiedValue(quotes))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
|
|
@ -46,14 +46,15 @@ ${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentc
|
|||
pub type T = super::SpecifiedValue;
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(context, input)
|
||||
.and_then(|result| {
|
||||
if let Either::Second(BorderStyle::hidden) = result {
|
||||
// The outline-style property accepts the same values as
|
||||
// border-style, except that 'hidden' is not a legal outline
|
||||
// style.
|
||||
Err(())
|
||||
Err(SelectorParseError::UnexpectedIdent("hidden".into()).into())
|
||||
} else {
|
||||
Ok(result)
|
||||
}
|
||||
|
|
|
@ -91,37 +91,43 @@
|
|||
}
|
||||
|
||||
impl Parse for computed_value::Keyword {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<computed_value::Keyword, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<computed_value::Keyword, ParseError<'i>> {
|
||||
use std::ascii::AsciiExt;
|
||||
use style_traits::cursor::Cursor;
|
||||
let ident = try!(input.expect_ident());
|
||||
if ident.eq_ignore_ascii_case("auto") {
|
||||
Ok(computed_value::Keyword::Auto)
|
||||
} else {
|
||||
Cursor::from_css_keyword(&ident).map(computed_value::Keyword::Cursor)
|
||||
Cursor::from_css_keyword(&ident)
|
||||
.map(computed_value::Keyword::Cursor)
|
||||
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
|
||||
fn parse_image<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<computed_value::Image, ParseError<'i>> {
|
||||
Ok(computed_value::Image {
|
||||
url: try!(SpecifiedUrl::parse(context, input)),
|
||||
hotspot: match input.try(|input| input.expect_number()) {
|
||||
Ok(number) => Some((number, try!(input.expect_number()))),
|
||||
Err(()) => None,
|
||||
Err(_) => None,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
computed_value::Keyword::parse(context, input)
|
||||
}
|
||||
|
||||
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut images = vec![];
|
||||
loop {
|
||||
match input.try(|input| parse_image(context, input)) {
|
||||
|
@ -129,7 +135,7 @@
|
|||
image.url.build_image_value();
|
||||
images.push(image)
|
||||
}
|
||||
Err(()) => break,
|
||||
Err(_) => break,
|
||||
}
|
||||
try!(input.expect_comma());
|
||||
}
|
||||
|
|
|
@ -339,27 +339,32 @@ ${helpers.predefined_type("object-position",
|
|||
}
|
||||
|
||||
/// [ row | column ] || dense
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
use self::computed_value::AutoFlow;
|
||||
|
||||
let mut value = None;
|
||||
let mut dense = false;
|
||||
|
||||
while !input.is_exhausted() {
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
let success = match_ignore_ascii_case! { &ident,
|
||||
"row" if value.is_none() => {
|
||||
value = Some(AutoFlow::Row);
|
||||
continue
|
||||
true
|
||||
},
|
||||
"column" if value.is_none() => {
|
||||
value = Some(AutoFlow::Column);
|
||||
continue
|
||||
true
|
||||
},
|
||||
"dense" if !dense => {
|
||||
dense = true;
|
||||
continue
|
||||
true
|
||||
},
|
||||
_ => return Err(())
|
||||
_ => false
|
||||
};
|
||||
if !success {
|
||||
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,7 +374,7 @@ ${helpers.predefined_type("object-position",
|
|||
dense: dense,
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,7 +440,8 @@ ${helpers.predefined_type("object-position",
|
|||
Either::Second(None_)
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(context, input)
|
||||
}
|
||||
|
||||
|
@ -457,13 +463,15 @@ ${helpers.predefined_type("object-position",
|
|||
impl ComputedValueAsSpecified for TemplateAreas {}
|
||||
|
||||
impl Parse for TemplateAreas {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let mut strings = vec![];
|
||||
while let Ok(string) = input.try(Parser::expect_string) {
|
||||
strings.push(string.into_owned().into_boxed_str());
|
||||
}
|
||||
|
||||
TemplateAreas::from_vec(strings)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,8 @@ ${helpers.single_keyword("mask-origin",
|
|||
background_size::get_initial_value()
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||
background_size::parse(context, input)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
|
|
@ -40,7 +40,8 @@ ${helpers.single_keyword("table-layout", "auto fixed",
|
|||
}
|
||||
|
||||
// never parse it, only set via presentation attribute
|
||||
fn parse(_: &ParserContext, _: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
Err(())
|
||||
fn parse<'i, 't>(_: &ParserContext, _: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
|
|
@ -104,7 +104,8 @@
|
|||
sides_are_logical: true,
|
||||
}
|
||||
}
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let first = try!(Side::parse(context, input));
|
||||
let second = input.try(|input| Side::parse(context, input)).ok();
|
||||
Ok(SpecifiedValue {
|
||||
|
@ -113,13 +114,14 @@
|
|||
})
|
||||
}
|
||||
impl Parse for Side {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Side, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Side, ParseError<'i>> {
|
||||
if let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"clip" => Ok(Side::Clip),
|
||||
"ellipsis" => Ok(Side::Ellipsis),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
} else {
|
||||
Ok(Side::String(try!(input.expect_string()).into_owned().into_boxed_str()))
|
||||
}
|
||||
|
@ -216,34 +218,39 @@ ${helpers.single_keyword("unicode-bidi",
|
|||
SpecifiedValue::empty()
|
||||
}
|
||||
/// none | [ underline || overline || line-through || blink ]
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut result = SpecifiedValue::empty();
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(result)
|
||||
}
|
||||
let mut empty = true;
|
||||
|
||||
while input.try(|input| {
|
||||
if let Ok(ident) = input.expect_ident() {
|
||||
match_ignore_ascii_case! { &ident,
|
||||
"underline" => if result.contains(UNDERLINE) { return Err(()) }
|
||||
else { empty = false; result.insert(UNDERLINE) },
|
||||
"overline" => if result.contains(OVERLINE) { return Err(()) }
|
||||
else { empty = false; result.insert(OVERLINE) },
|
||||
"line-through" => if result.contains(LINE_THROUGH) { return Err(()) }
|
||||
else { empty = false; result.insert(LINE_THROUGH) },
|
||||
"blink" => if result.contains(BLINK) { return Err(()) }
|
||||
else { empty = false; result.insert(BLINK) },
|
||||
_ => return Err(())
|
||||
loop {
|
||||
let result: Result<_, ParseError> = input.try(|input| {
|
||||
match input.expect_ident() {
|
||||
Ok(ident) => {
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"underline" => if result.contains(UNDERLINE) { Err(()) }
|
||||
else { empty = false; result.insert(UNDERLINE); Ok(()) },
|
||||
"overline" => if result.contains(OVERLINE) { Err(()) }
|
||||
else { empty = false; result.insert(OVERLINE); Ok(()) },
|
||||
"line-through" => if result.contains(LINE_THROUGH) { Err(()) }
|
||||
else { empty = false; result.insert(LINE_THROUGH); Ok(()) },
|
||||
"blink" => if result.contains(BLINK) { Err(()) }
|
||||
else { empty = false; result.insert(BLINK); Ok(()) },
|
||||
_ => Err(())
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
} else {
|
||||
return Err(());
|
||||
Err(e) => return Err(e.into())
|
||||
}
|
||||
Ok(())
|
||||
}).is_ok() {
|
||||
});
|
||||
if result.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !empty { Ok(result) } else { Err(()) }
|
||||
if !empty { Ok(result) } else { Err(StyleParseError::UnspecifiedError.into()) }
|
||||
}
|
||||
|
||||
% if product == "servo":
|
||||
|
|
|
@ -76,11 +76,12 @@ ${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet"
|
|||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
match try!(input.expect_integer()) {
|
||||
0 => Ok(computed_value::T(false)),
|
||||
1 => Ok(computed_value::T(true)),
|
||||
_ => Err(()),
|
||||
_ => Err(StyleParseError::UnspecifiedError.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ use stylearc::{Arc, UniqueArc};
|
|||
use app_units::Au;
|
||||
#[cfg(feature = "servo")] use cssparser::RGBA;
|
||||
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
||||
use cssparser::ParserInput;
|
||||
use error_reporting::ParseErrorReporter;
|
||||
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
|
||||
use computed_values;
|
||||
|
@ -33,9 +34,10 @@ use media_queries::Device;
|
|||
use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext};
|
||||
use properties::animated_properties::TransitionProperty;
|
||||
#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
|
||||
use selectors::parser::SelectorParseError;
|
||||
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
|
||||
use shared_lock::StylesheetGuards;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use style_traits::{HasViewportPercentage, ToCss, ParseError, PropertyDeclarationParseError};
|
||||
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
|
||||
#[cfg(feature = "servo")] use values::Either;
|
||||
use values::generics::text::LineHeight;
|
||||
|
@ -185,6 +187,7 @@ macro_rules! unwrap_or_initial {
|
|||
pub mod shorthands {
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
use values::specified;
|
||||
|
||||
<%include file="/shorthand/serialize.mako.rs" />
|
||||
|
@ -213,9 +216,11 @@ pub mod shorthands {
|
|||
use parser::ParserContext;
|
||||
use properties::{SourcePropertyDeclaration, AllShorthand, ShorthandId, UnparsedValue};
|
||||
use stylearc::Arc;
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
|
||||
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
|
||||
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
|
||||
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
|
||||
context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<(), ParseError<'i>> {
|
||||
// This function is like the parse() that is generated by
|
||||
// helpers:shorthand, but since the only values for the 'all'
|
||||
// shorthand when not just a single CSS-wide keyword is one
|
||||
|
@ -239,7 +244,7 @@ pub mod shorthands {
|
|||
}));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -414,6 +419,7 @@ impl PropertyDeclarationIdSet {
|
|||
{
|
||||
f(&
|
||||
::custom_properties::substitute(css, first_token_type, custom_properties)
|
||||
.ok()
|
||||
.and_then(|css| {
|
||||
// As of this writing, only the base URL is used for property values:
|
||||
//
|
||||
|
@ -425,7 +431,8 @@ impl PropertyDeclarationIdSet {
|
|||
None,
|
||||
PARSING_MODE_DEFAULT,
|
||||
quirks_mode);
|
||||
Parser::new(&css).parse_entirely(|input| {
|
||||
let mut input = ParserInput::new(&css);
|
||||
Parser::new(&mut input).parse_entirely(|input| {
|
||||
match from_shorthand {
|
||||
None => {
|
||||
longhands::${property.ident}
|
||||
|
@ -434,7 +441,7 @@ impl PropertyDeclarationIdSet {
|
|||
Some(ShorthandId::All) => {
|
||||
// No need to parse the 'all' shorthand as anything other than a CSS-wide
|
||||
// keyword, after variable substitution.
|
||||
Err(())
|
||||
Err(SelectorParseError::UnexpectedIdent("all".into()).into())
|
||||
}
|
||||
% for shorthand in data.shorthands_except_all():
|
||||
% if property in shorthand.sub_properties:
|
||||
|
@ -448,7 +455,7 @@ impl PropertyDeclarationIdSet {
|
|||
% endfor
|
||||
_ => unreachable!()
|
||||
}
|
||||
})
|
||||
}).ok()
|
||||
})
|
||||
.unwrap_or(
|
||||
// Invalid at computed-value time.
|
||||
|
@ -500,10 +507,11 @@ impl CSSWideKeyword {
|
|||
}
|
||||
|
||||
impl Parse for CSSWideKeyword {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
input.expect_exhausted()?;
|
||||
CSSWideKeyword::from_ident(&ident).ok_or(())
|
||||
CSSWideKeyword::from_ident(&ident)
|
||||
.ok_or(SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -946,7 +954,7 @@ impl PropertyId {
|
|||
/// Returns a given property from the string `s`.
|
||||
///
|
||||
/// Returns Err(()) for unknown non-custom properties
|
||||
pub fn parse(property_name: Cow<str>) -> Result<Self, ()> {
|
||||
pub fn parse<'i>(property_name: Cow<'i, str>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(name) = ::custom_properties::parse_name(&property_name) {
|
||||
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
|
||||
}
|
||||
|
@ -971,7 +979,7 @@ impl PropertyId {
|
|||
match static_id(&property_name) {
|
||||
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
|
||||
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)),
|
||||
None => Err(()),
|
||||
None => Err(SelectorParseError::UnexpectedIdent(property_name).into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1095,24 +1103,6 @@ impl HasViewportPercentage for PropertyDeclaration {
|
|||
}
|
||||
}
|
||||
|
||||
/// The result of parsing a property declaration.
|
||||
#[derive(Eq, PartialEq, Copy, Clone)]
|
||||
pub enum PropertyDeclarationParseError {
|
||||
/// The property declaration was for an unknown property.
|
||||
UnknownProperty,
|
||||
/// The property declaration was for a disabled experimental property.
|
||||
ExperimentalProperty,
|
||||
/// The property declaration contained an invalid value.
|
||||
InvalidValue,
|
||||
/// The declaration contained an animation property, and we were parsing
|
||||
/// this as a keyframe block (so that property should be ignored).
|
||||
///
|
||||
/// See: https://drafts.csswg.org/css-animations/#keyframes
|
||||
AnimationPropertyInKeyframeBlock,
|
||||
/// The property is not allowed within a page rule.
|
||||
NotAllowedInPageRule,
|
||||
}
|
||||
|
||||
impl fmt::Debug for PropertyDeclaration {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(self.id().to_css(f));
|
||||
|
@ -1407,9 +1397,9 @@ impl PropertyDeclaration {
|
|||
PropertyId::Custom(name) => {
|
||||
let value = match input.try(|i| CSSWideKeyword::parse(context, i)) {
|
||||
Ok(keyword) => DeclaredValueOwned::CSSWideKeyword(keyword),
|
||||
Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) {
|
||||
Err(_) => match ::custom_properties::SpecifiedValue::parse(context, input) {
|
||||
Ok(value) => DeclaredValueOwned::Value(value),
|
||||
Err(()) => return Err(PropertyDeclarationParseError::InvalidValue),
|
||||
Err(_) => return Err(PropertyDeclarationParseError::InvalidValue),
|
||||
}
|
||||
};
|
||||
declarations.push(PropertyDeclaration::Custom(name, value));
|
||||
|
@ -1442,7 +1432,7 @@ impl PropertyDeclaration {
|
|||
declarations.push(value);
|
||||
Ok(())
|
||||
},
|
||||
Err(()) => Err(PropertyDeclarationParseError::InvalidValue),
|
||||
Err(_) => Err(PropertyDeclarationParseError::InvalidValue),
|
||||
}
|
||||
% else:
|
||||
Err(PropertyDeclarationParseError::UnknownProperty)
|
||||
|
@ -1485,9 +1475,9 @@ impl PropertyDeclaration {
|
|||
% endif
|
||||
Ok(())
|
||||
},
|
||||
Err(()) => {
|
||||
Err(_) => {
|
||||
shorthands::${shorthand.ident}::parse_into(declarations, context, input)
|
||||
.map_err(|()| PropertyDeclarationParseError::InvalidValue)
|
||||
.map_err(|_| PropertyDeclarationParseError::InvalidValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut background_color = None;
|
||||
|
||||
% for name in "image position_x position_y repeat size attachment origin clip".split():
|
||||
|
@ -42,7 +43,7 @@
|
|||
// background-color can only be in the last element, so if it
|
||||
// is parsed anywhere before, the value is invalid.
|
||||
if background_color.is_some() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
% for name in "image position repeat size attachment origin clip".split():
|
||||
|
@ -107,7 +108,7 @@
|
|||
% endfor
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -194,7 +195,8 @@
|
|||
use values::specified::AllowQuirks;
|
||||
use values::specified::position::Position;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut position_x = background_position_x::SpecifiedValue(Vec::new());
|
||||
let mut position_y = background_position_y::SpecifiedValue(Vec::new());
|
||||
let mut any = false;
|
||||
|
@ -207,7 +209,7 @@
|
|||
Ok(())
|
||||
})?;
|
||||
if !any {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(expanded! {
|
||||
|
|
|
@ -20,7 +20,8 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
|||
use values::generics::rect::Rect;
|
||||
use values::specified::{AllowQuirks, BorderSideWidth};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let rect = Rect::parse_with(context, input, |_, i| {
|
||||
BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes)
|
||||
})?;
|
||||
|
@ -43,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
|||
</%helpers:shorthand>
|
||||
|
||||
|
||||
pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<(specified::Color,
|
||||
specified::BorderStyle,
|
||||
specified::BorderSideWidth), ()> {
|
||||
pub fn parse_border<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<(specified::Color,
|
||||
specified::BorderStyle,
|
||||
specified::BorderSideWidth), ParseError<'i>> {
|
||||
use values::specified::{Color, BorderStyle, BorderSideWidth};
|
||||
let _unused = context;
|
||||
let mut color = None;
|
||||
|
@ -82,7 +83,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
style.unwrap_or(BorderStyle::none),
|
||||
width.unwrap_or(BorderSideWidth::Medium)))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +102,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
alias="${maybe_moz_logical_alias(product, (side, logical), '-moz-border-%s')}"
|
||||
spec="${spec}">
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let (color, style, width) = try!(super::parse_border(context, input));
|
||||
Ok(expanded! {
|
||||
border_${to_rust_ident(side)}_color: color,
|
||||
|
@ -139,7 +141,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
_moz_border_bottom_colors, _moz_border_left_colors};
|
||||
% endif
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
||||
use properties::longhands::{border_image_source, border_image_width};
|
||||
|
||||
|
@ -209,7 +212,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
use values::specified::border::BorderRadius;
|
||||
use parser::Parse;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let radii = try!(BorderRadius::parse(context, input));
|
||||
Ok(expanded! {
|
||||
border_top_left_radius: radii.top_left,
|
||||
|
@ -242,12 +246,13 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
||||
use properties::longhands::{border_image_source, border_image_width};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
% for name in "outset repeat slice source width".split():
|
||||
let mut border_image_${name} = border_image_${name}::get_initial_specified_value();
|
||||
% endfor
|
||||
|
||||
try!(input.try(|input| {
|
||||
let result: Result<_, ParseError> = input.try(|input| {
|
||||
% for name in "outset repeat slice source width".split():
|
||||
let mut ${name} = None;
|
||||
% endfor
|
||||
|
@ -256,7 +261,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
if let Ok(value) = input.try(|input| border_image_slice::parse(context, input)) {
|
||||
slice = Some(value);
|
||||
// Parse border image width and outset, if applicable.
|
||||
let maybe_width_outset: Result<_, ()> = input.try(|input| {
|
||||
let maybe_width_outset: Result<_, ParseError> = input.try(|input| {
|
||||
try!(input.expect_delim('/'));
|
||||
|
||||
// Parse border image width, if applicable.
|
||||
|
@ -269,7 +274,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
border_image_outset::parse(context, input)
|
||||
}).ok();
|
||||
if w.is_none() && o.is_none() {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
else {
|
||||
Ok((w, o))
|
||||
|
@ -305,9 +310,10 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
|||
% endfor
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}));
|
||||
});
|
||||
try!(result);
|
||||
|
||||
Ok(expanded! {
|
||||
% for name in "outset repeat slice source width".split():
|
||||
|
|
|
@ -11,29 +11,33 @@
|
|||
use properties::longhands::overflow_x::SpecifiedValue;
|
||||
% endif
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
% if product == "gecko":
|
||||
let moz_kw_found = input.try(|i| match_ignore_ascii_case! {
|
||||
&i.expect_ident()?,
|
||||
"-moz-scrollbars-horizontal" => {
|
||||
Ok(expanded! {
|
||||
overflow_x: SpecifiedValue::scroll,
|
||||
overflow_y: SpecifiedValue::hidden,
|
||||
})
|
||||
}
|
||||
"-moz-scrollbars-vertical" => {
|
||||
Ok(expanded! {
|
||||
overflow_x: SpecifiedValue::hidden,
|
||||
overflow_y: SpecifiedValue::scroll,
|
||||
})
|
||||
}
|
||||
"-moz-scrollbars-none" => {
|
||||
Ok(expanded! {
|
||||
overflow_x: SpecifiedValue::hidden,
|
||||
overflow_y: SpecifiedValue::hidden,
|
||||
})
|
||||
}
|
||||
_ => Err(())
|
||||
let moz_kw_found = input.try(|i| {
|
||||
let ident = i.expect_ident()?;
|
||||
(match_ignore_ascii_case! {
|
||||
&ident,
|
||||
"-moz-scrollbars-horizontal" => {
|
||||
Ok(expanded! {
|
||||
overflow_x: SpecifiedValue::scroll,
|
||||
overflow_y: SpecifiedValue::hidden,
|
||||
})
|
||||
}
|
||||
"-moz-scrollbars-vertical" => {
|
||||
Ok(expanded! {
|
||||
overflow_x: SpecifiedValue::hidden,
|
||||
overflow_y: SpecifiedValue::scroll,
|
||||
})
|
||||
}
|
||||
"-moz-scrollbars-none" => {
|
||||
Ok(expanded! {
|
||||
overflow_x: SpecifiedValue::hidden,
|
||||
overflow_y: SpecifiedValue::hidden,
|
||||
})
|
||||
}
|
||||
_ => Err(())
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
});
|
||||
if moz_kw_found.is_ok() {
|
||||
return moz_kw_found
|
||||
|
@ -88,14 +92,16 @@ macro_rules! try_parse_one {
|
|||
use properties::longhands::transition_${prop};
|
||||
% endfor
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
struct SingleTransition {
|
||||
% for prop in "property duration timing_function delay".split():
|
||||
transition_${prop}: transition_${prop}::SingleSpecifiedValue,
|
||||
% endfor
|
||||
}
|
||||
|
||||
fn parse_one_transition(context: &ParserContext, input: &mut Parser) -> Result<SingleTransition,()> {
|
||||
fn parse_one_transition<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SingleTransition,ParseError<'i>> {
|
||||
% for prop in "property duration timing_function delay".split():
|
||||
let mut ${prop} = None;
|
||||
% endfor
|
||||
|
@ -123,7 +129,7 @@ macro_rules! try_parse_one {
|
|||
% endfor
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,14 +208,16 @@ macro_rules! try_parse_one {
|
|||
use properties::longhands::animation_${prop};
|
||||
% endfor
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
struct SingleAnimation {
|
||||
% for prop in props:
|
||||
animation_${prop}: animation_${prop}::SingleSpecifiedValue,
|
||||
% endfor
|
||||
}
|
||||
|
||||
fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result<SingleAnimation,()> {
|
||||
fn parse_one_animation<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SingleAnimation,ParseError<'i>> {
|
||||
% for prop in props:
|
||||
let mut ${prop} = None;
|
||||
% endfor
|
||||
|
@ -237,7 +245,7 @@ macro_rules! try_parse_one {
|
|||
|
||||
// If nothing is parsed, this is an invalid entry.
|
||||
if parsed == 0 {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
Ok(SingleAnimation {
|
||||
% for prop in props:
|
||||
|
@ -303,7 +311,8 @@ macro_rules! try_parse_one {
|
|||
spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
|
||||
use properties::longhands::scroll_snap_type_x;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let result = try!(scroll_snap_type_x::parse(context, input));
|
||||
Ok(expanded! {
|
||||
scroll_snap_type_x: result,
|
||||
|
@ -331,7 +340,8 @@ macro_rules! try_parse_one {
|
|||
spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
|
||||
use properties::longhands::transform;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
Ok(expanded! {
|
||||
transform: transform::parse_prefixed(context, input)?,
|
||||
})
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
extra_prefixes="moz" spec="https://drafts.csswg.org/css-multicol/#propdef-columns">
|
||||
use properties::longhands::{column_count, column_width};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
|
||||
let mut column_count = None;
|
||||
let mut column_width = None;
|
||||
|
@ -40,7 +41,7 @@
|
|||
|
||||
let values = autos + column_count.iter().len() + column_width.iter().len();
|
||||
if values == 0 || values > 2 {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
Ok(expanded! {
|
||||
column_count: unwrap_or_initial!(column_count),
|
||||
|
@ -65,7 +66,8 @@
|
|||
use properties::longhands::{column_rule_width, column_rule_style};
|
||||
use properties::longhands::column_rule_color;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
% for name in "width style color".split():
|
||||
let mut column_rule_${name} = None;
|
||||
% endfor
|
||||
|
@ -92,7 +94,7 @@
|
|||
column_rule_color: unwrap_or_initial!(column_rule_color),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@
|
|||
% endif
|
||||
use self::font_family::SpecifiedValue as FontFamily;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut nb_normals = 0;
|
||||
let mut style = None;
|
||||
let mut variant_caps = None;
|
||||
|
@ -97,7 +98,7 @@
|
|||
}
|
||||
if size.is_none() ||
|
||||
(count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
|
||||
Some(try!(LineHeight::parse(context, input)))
|
||||
|
@ -239,7 +240,8 @@
|
|||
% endfor
|
||||
% endif
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut nb_normals = 0;
|
||||
let mut caps = None;
|
||||
loop {
|
||||
|
@ -264,7 +266,7 @@
|
|||
}
|
||||
let count = count(&caps) + nb_normals;
|
||||
if count == 0 || count > 1 {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(expanded! {
|
||||
font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
spec="https://www.w3.org/TR/SVG2/painting.html#MarkerShorthand">
|
||||
use values::specified::UrlOrNone;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
use parser::Parse;
|
||||
let url = UrlOrNone::parse(context, input)?;
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
spec="https://drafts.csswg.org/css-text-decor-3/#text-emphasis-property">
|
||||
use properties::longhands::{text_emphasis_color, text_emphasis_style};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut color = None;
|
||||
let mut style = None;
|
||||
|
||||
|
@ -34,7 +35,7 @@
|
|||
text_emphasis_style: unwrap_or_initial!(text_emphasis_style, style),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +57,8 @@
|
|||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
|
||||
use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut color = None;
|
||||
let mut width = None;
|
||||
loop {
|
||||
|
@ -82,7 +84,7 @@
|
|||
_webkit_text_stroke_width: unwrap_or_initial!(_webkit_text_stroke_width, width),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
use properties::longhands::{list_style_image, list_style_position, list_style_type};
|
||||
use values::{Either, None_};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
// `none` is ambiguous until we've finished parsing the shorthands, so we count the number
|
||||
// of times we see it.
|
||||
let mut nones = 0u8;
|
||||
|
@ -19,7 +20,7 @@
|
|||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
nones = nones + 1;
|
||||
if nones > 2 {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent("none".into()).into())
|
||||
}
|
||||
any = true;
|
||||
continue
|
||||
|
@ -104,7 +105,7 @@
|
|||
list_style_type: unwrap_or_initial!(list_style_type),
|
||||
})
|
||||
}
|
||||
_ => Err(()),
|
||||
_ => Err(StyleParseError::UnspecifiedError.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
% for name in "image mode position_x position_y size repeat origin clip composite".split():
|
||||
let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::new());
|
||||
% endfor
|
||||
|
@ -103,7 +104,7 @@
|
|||
% endfor
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -180,7 +181,8 @@
|
|||
use values::specified::position::Position;
|
||||
use parser::Parse;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut position_x = mask_position_x::SpecifiedValue(Vec::new());
|
||||
let mut position_y = mask_position_y::SpecifiedValue(Vec::new());
|
||||
let mut any = false;
|
||||
|
@ -193,7 +195,7 @@
|
|||
Ok(())
|
||||
})?;
|
||||
if any == false {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(expanded! {
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
use values::specified;
|
||||
use parser::Parse;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let _unused = context;
|
||||
let mut color = None;
|
||||
let mut style = None;
|
||||
|
@ -47,7 +48,7 @@
|
|||
outline_width: unwrap_or_initial!(outline_width, width),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,8 @@
|
|||
use values::specified::border::BorderRadius;
|
||||
use parser::Parse;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let radii = try!(BorderRadius::parse(context, input));
|
||||
Ok(expanded! {
|
||||
_moz_outline_radius_topleft: radii.top_left,
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
|
||||
use properties::longhands::{flex_direction, flex_wrap};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut direction = None;
|
||||
let mut wrap = None;
|
||||
loop {
|
||||
|
@ -28,7 +29,7 @@
|
|||
}
|
||||
|
||||
if direction.is_none() && wrap.is_none() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(expanded! {
|
||||
flex_direction: unwrap_or_initial!(flex_direction, direction),
|
||||
|
@ -50,14 +51,15 @@
|
|||
spec="https://drafts.csswg.org/css-flexbox/#flex-property">
|
||||
use values::specified::Number;
|
||||
|
||||
fn parse_flexibility(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<(Number, Option<Number>),()> {
|
||||
fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<(Number, Option<Number>),ParseError<'i>> {
|
||||
let grow = try!(Number::parse_non_negative(context, input));
|
||||
let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
|
||||
Ok((grow, shrink))
|
||||
}
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut grow = None;
|
||||
let mut shrink = None;
|
||||
let mut basis = None;
|
||||
|
@ -87,7 +89,7 @@
|
|||
}
|
||||
|
||||
if grow.is_none() && basis.is_none() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(expanded! {
|
||||
flex_grow: grow.unwrap_or(Number::new(1.0)),
|
||||
|
@ -118,7 +120,8 @@
|
|||
products="gecko">
|
||||
use properties::longhands::{grid_row_gap, grid_column_gap};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let row_gap = grid_row_gap::parse(context, input)?;
|
||||
let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());
|
||||
|
||||
|
@ -152,7 +155,8 @@
|
|||
// NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
|
||||
// the other. This might not be a big deal for now, but we should consider looking into this in the future
|
||||
// to limit the amount of code generated.
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let start = input.try(|i| GridLine::parse(context, i))?;
|
||||
let end = if input.try(|i| i.expect_delim('/')).is_ok() {
|
||||
GridLine::parse(context, input)?
|
||||
|
@ -189,7 +193,8 @@
|
|||
use parser::Parse;
|
||||
|
||||
// The code is the same as `grid-{row,column}` except that this can have four values at most.
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
fn line_with_ident_from(other: &GridLine) -> GridLine {
|
||||
let mut this = GridLine::default();
|
||||
if other.line_num.is_none() && !other.is_span {
|
||||
|
@ -259,8 +264,9 @@
|
|||
use values::specified::grid::parse_line_names;
|
||||
|
||||
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
|
||||
pub fn parse_grid_template(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>), ()> {
|
||||
pub fn parse_grid_template<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>),
|
||||
ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_)))
|
||||
}
|
||||
|
@ -295,7 +301,8 @@
|
|||
line_names.push(vec![]); // should be one longer than track sizes
|
||||
}
|
||||
|
||||
let template_areas = TemplateAreas::from_vec(strings)?;
|
||||
let template_areas = TemplateAreas::from_vec(strings)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError)?;
|
||||
let template_rows = TrackList {
|
||||
list_type: TrackListType::Normal,
|
||||
values: values,
|
||||
|
@ -306,7 +313,7 @@
|
|||
let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() {
|
||||
let track_list = TrackList::parse(context, input)?;
|
||||
if track_list.list_type != TrackListType::Explicit {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
Either::First(track_list)
|
||||
|
@ -326,7 +333,8 @@
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let (rows, columns, areas) = parse_grid_template(context, input)?;
|
||||
Ok(expanded! {
|
||||
grid_template_rows: rows,
|
||||
|
@ -410,7 +418,8 @@
|
|||
use values::{Either, None_};
|
||||
use values::specified::{LengthOrPercentage, TrackSize};
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let mut temp_rows = Either::Second(None_);
|
||||
let mut temp_cols = Either::Second(None_);
|
||||
let mut temp_areas = Either::Second(None_);
|
||||
|
@ -418,7 +427,8 @@
|
|||
let mut auto_cols = TrackSize::default();
|
||||
let mut flow = grid_auto_flow::get_initial_value();
|
||||
|
||||
fn parse_auto_flow(input: &mut Parser, is_row: bool) -> Result<SpecifiedAutoFlow, ()> {
|
||||
fn parse_auto_flow<'i, 't>(input: &mut Parser<'i, 't>, is_row: bool)
|
||||
-> Result<SpecifiedAutoFlow, ParseError<'i>> {
|
||||
let mut auto_flow = None;
|
||||
let mut dense = false;
|
||||
for _ in 0..2 {
|
||||
|
@ -440,7 +450,7 @@
|
|||
autoflow: flow,
|
||||
dense: dense,
|
||||
}
|
||||
}).ok_or(())
|
||||
}).ok_or(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
if let Ok((rows, cols, areas)) = input.try(|i| super::grid_template::parse_grid_template(context, i)) {
|
||||
|
@ -506,15 +516,16 @@
|
|||
use properties::longhands::align_content;
|
||||
use properties::longhands::justify_content;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let align = align_content::parse(context, input)?;
|
||||
if align.has_extra_flags() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
let justify = input.try(|input| justify_content::parse(context, input))
|
||||
.unwrap_or(justify_content::SpecifiedValue::from(align));
|
||||
if justify.has_extra_flags() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(expanded! {
|
||||
|
@ -541,14 +552,15 @@
|
|||
use values::specified::align::AlignJustifySelf;
|
||||
use parser::Parse;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let align = AlignJustifySelf::parse(context, input)?;
|
||||
if align.has_extra_flags() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());
|
||||
if justify.has_extra_flags() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(expanded! {
|
||||
|
@ -582,15 +594,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
let align = AlignItems::parse(context, input)?;
|
||||
if align.has_extra_flags() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
let justify = input.try(|input| JustifyItems::parse(context, input))
|
||||
.unwrap_or(JustifyItems::from(align));
|
||||
if justify.has_extra_flags() {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(expanded! {
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
use properties::longhands::text_decoration_line;
|
||||
% endif
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Longhands, ParseError<'i>> {
|
||||
% if product == "gecko" or data.testing:
|
||||
let (mut line, mut style, mut color, mut any) = (None, None, None, false);
|
||||
% else:
|
||||
|
@ -47,7 +48,7 @@
|
|||
}
|
||||
|
||||
if !any {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(expanded! {
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use cssparser::Parser as CssParser;
|
||||
use cssparser::{Parser as CssParser, ParserInput};
|
||||
use selectors::Element;
|
||||
use selectors::parser::SelectorList;
|
||||
use std::fmt::Debug;
|
||||
use style_traits::ParseError;
|
||||
use stylesheets::{Origin, Namespaces};
|
||||
|
||||
/// A convenient alias for the type that represents an attribute value used for
|
||||
|
@ -59,13 +60,14 @@ impl<'a> SelectorParser<'a> {
|
|||
///
|
||||
/// This is used for some DOM APIs like `querySelector`.
|
||||
pub fn parse_author_origin_no_namespace(input: &str)
|
||||
-> Result<SelectorList<SelectorImpl>, ()> {
|
||||
-> Result<SelectorList<SelectorImpl>, ParseError> {
|
||||
let namespaces = Namespaces::default();
|
||||
let parser = SelectorParser {
|
||||
stylesheet_origin: Origin::Author,
|
||||
namespaces: &namespaces,
|
||||
};
|
||||
SelectorList::parse(&parser, &mut CssParser::new(input))
|
||||
let mut input = ParserInput::new(input);
|
||||
SelectorList::parse(&parser, &mut CssParser::new(&mut input))
|
||||
}
|
||||
|
||||
/// Whether we're parsing selectors in a user-agent stylesheet.
|
||||
|
|
|
@ -13,9 +13,10 @@ use media_queries::MediaType;
|
|||
use parser::ParserContext;
|
||||
use properties::{ComputedValues, StyleBuilder};
|
||||
use properties::longhands::font_size;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::fmt;
|
||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
||||
use style_traits::{CSSPixel, ToCss};
|
||||
use style_traits::{CSSPixel, ToCss, ParseError};
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use values::computed::{self, ToComputedValue};
|
||||
use values::specified;
|
||||
|
@ -151,7 +152,8 @@ impl Expression {
|
|||
/// ```
|
||||
///
|
||||
/// Only supports width and width ranges for now.
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
try!(input.expect_parenthesis_block());
|
||||
input.parse_nested_block(|input| {
|
||||
let name = try!(input.expect_ident());
|
||||
|
@ -167,7 +169,7 @@ impl Expression {
|
|||
"width" => {
|
||||
ExpressionKind::Width(Range::Eq(try!(specified::Length::parse_non_negative(context, input))))
|
||||
},
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use restyle_hints::ElementSnapshot;
|
|||
use selector_parser::{AttrValue as SelectorAttrValue, ElementExt, PseudoElementCascadeType, SelectorParser};
|
||||
use selectors::Element;
|
||||
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
|
||||
use selectors::parser::SelectorMethods;
|
||||
use selectors::parser::{SelectorMethods, SelectorParseError};
|
||||
use selectors::visitor::SelectorVisitor;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
|
@ -24,6 +24,7 @@ use std::fmt;
|
|||
use std::fmt::Debug;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
|
||||
/// A pseudo-element, both public and private.
|
||||
///
|
||||
|
@ -300,10 +301,12 @@ impl ::selectors::SelectorImpl for SelectorImpl {
|
|||
type BorrowedNamespaceUrl = Namespace;
|
||||
}
|
||||
|
||||
impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||
impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||
type Impl = SelectorImpl;
|
||||
type Error = StyleParseError<'i>;
|
||||
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
|
||||
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||
use self::NonTSPseudoClass::*;
|
||||
let pseudo_class = match_ignore_ascii_case! { &name,
|
||||
"active" => Active,
|
||||
|
@ -323,20 +326,21 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
"visited" => Visited,
|
||||
"-servo-nonzero-border" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(());
|
||||
return Err(SelectorParseError::UnexpectedIdent(
|
||||
"-servo-nonzero-border".into()).into());
|
||||
}
|
||||
ServoNonZeroBorder
|
||||
},
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
|
||||
};
|
||||
|
||||
Ok(pseudo_class)
|
||||
}
|
||||
|
||||
fn parse_non_ts_functional_pseudo_class(&self,
|
||||
name: Cow<str>,
|
||||
parser: &mut CssParser)
|
||||
-> Result<NonTSPseudoClass, ()> {
|
||||
fn parse_non_ts_functional_pseudo_class<'t>(&self,
|
||||
name: Cow<'i, str>,
|
||||
parser: &mut CssParser<'i, 't>)
|
||||
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||
use self::NonTSPseudoClass::*;
|
||||
let pseudo_class = match_ignore_ascii_case!{ &name,
|
||||
"lang" => {
|
||||
|
@ -344,18 +348,17 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
}
|
||||
"-servo-case-sensitive-type-attr" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(());
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into());
|
||||
}
|
||||
ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?))
|
||||
}
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
};
|
||||
|
||||
Ok(pseudo_class)
|
||||
}
|
||||
|
||||
fn parse_pseudo_element(&self, name: Cow<str>)
|
||||
-> Result<PseudoElement, ()> {
|
||||
fn parse_pseudo_element(&self, name: Cow<'i, str>) -> Result<PseudoElement, ParseError<'i>> {
|
||||
use self::PseudoElement::*;
|
||||
let pseudo_element = match_ignore_ascii_case! { &name,
|
||||
"before" => Before,
|
||||
|
@ -363,77 +366,78 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
|||
"selection" => Selection,
|
||||
"-servo-details-summary" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
DetailsSummary
|
||||
},
|
||||
"-servo-details-content" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
DetailsContent
|
||||
},
|
||||
"-servo-text" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoText
|
||||
},
|
||||
"-servo-input-text" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoInputText
|
||||
},
|
||||
"-servo-table-wrapper" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoTableWrapper
|
||||
},
|
||||
"-servo-anonymous-table-wrapper" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoAnonymousTableWrapper
|
||||
},
|
||||
"-servo-anonymous-table" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoAnonymousTable
|
||||
},
|
||||
"-servo-anonymous-table-row" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoAnonymousTableRow
|
||||
},
|
||||
"-servo-anonymous-table-cell" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoAnonymousTableCell
|
||||
},
|
||||
"-servo-anonymous-block" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoAnonymousBlock
|
||||
},
|
||||
"-servo-inline-block-wrapper" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoInlineBlockWrapper
|
||||
},
|
||||
"-servo-input-absolute" => {
|
||||
if !self.in_user_agent_stylesheet() {
|
||||
return Err(())
|
||||
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
}
|
||||
ServoInlineAbsolute
|
||||
},
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||
|
||||
};
|
||||
|
||||
Ok(pseudo_element)
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::fmt::{self, Write};
|
|||
// nonzero optimization is important in keeping the size of SpecifiedUrl below
|
||||
// the threshold.
|
||||
use std::sync::Arc;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
|
||||
/// A specified url() value for servo.
|
||||
///
|
||||
|
@ -43,7 +43,7 @@ impl SpecifiedUrl {
|
|||
/// gecko version.
|
||||
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
||||
context: &ParserContext)
|
||||
-> Result<Self, ()> {
|
||||
-> Result<Self, ParseError<'a>> {
|
||||
let serialization = Arc::new(url.into_owned());
|
||||
let resolved = context.url_data.join(&serialization).ok();
|
||||
Ok(SpecifiedUrl {
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
//! initially in CSS Conditional Rules Module Level 3, @document has been postponed to the level 4.
|
||||
//! We implement the prefixed `@-moz-document`.
|
||||
|
||||
use cssparser::{Parser, Token, SourceLocation};
|
||||
use cssparser::{Parser, Token, SourceLocation, BasicParseError};
|
||||
use media_queries::Device;
|
||||
use parser::{Parse, ParserContext};
|
||||
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use stylearc::Arc;
|
||||
use stylesheets::CssRules;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
@ -90,9 +90,10 @@ macro_rules! parse_quoted_or_unquoted_string {
|
|||
match input.next() {
|
||||
Ok(Token::QuotedString(value)) =>
|
||||
Ok($url_matching_function(value.into_owned())),
|
||||
_ => Err(()),
|
||||
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}).or_else(|_| {
|
||||
}).or_else(|_: ParseError| {
|
||||
while let Ok(_) = input.next() {}
|
||||
Ok($url_matching_function(input.slice_from(start).to_string()))
|
||||
})
|
||||
|
@ -102,8 +103,8 @@ macro_rules! parse_quoted_or_unquoted_string {
|
|||
|
||||
impl UrlMatchingFunction {
|
||||
/// Parse a URL matching function for a`@document` rule's condition.
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<UrlMatchingFunction, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<UrlMatchingFunction, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_function_matching("url-prefix")).is_ok() {
|
||||
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::UrlPrefix)
|
||||
} else if input.try(|input| input.expect_function_matching("domain")).is_ok() {
|
||||
|
@ -115,7 +116,7 @@ impl UrlMatchingFunction {
|
|||
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||
Ok(UrlMatchingFunction::Url(url))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,8 +190,8 @@ pub struct DocumentCondition(Vec<UrlMatchingFunction>);
|
|||
|
||||
impl DocumentCondition {
|
||||
/// Parse a document condition.
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
input.parse_comma_separated(|input| UrlMatchingFunction::parse(context, input))
|
||||
.map(DocumentCondition)
|
||||
}
|
||||
|
|
|
@ -4,18 +4,20 @@
|
|||
|
||||
//! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
|
||||
|
||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
|
||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput};
|
||||
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation};
|
||||
use error_reporting::NullReporter;
|
||||
use error_reporting::{NullReporter, ContextualParseError};
|
||||
use parser::{PARSING_MODE_DEFAULT, ParserContext, log_css_error};
|
||||
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
||||
use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration};
|
||||
use properties::LonghandIdSet;
|
||||
use properties::animated_properties::TransitionProperty;
|
||||
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::{DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use stylearc::Arc;
|
||||
use stylesheets::{CssRuleType, Stylesheet};
|
||||
use stylesheets::rule_parser::VendorPrefix;
|
||||
|
@ -61,7 +63,8 @@ impl KeyframesRule {
|
|||
/// Related spec:
|
||||
/// https://drafts.csswg.org/css-animations-1/#interface-csskeyframesrule-findrule
|
||||
pub fn find_rule(&self, guard: &SharedRwLockReadGuard, selector: &str) -> Option<usize> {
|
||||
if let Ok(selector) = Parser::new(selector).parse_entirely(KeyframeSelector::parse) {
|
||||
let mut input = ParserInput::new(selector);
|
||||
if let Ok(selector) = Parser::new(&mut input).parse_entirely(KeyframeSelector::parse) {
|
||||
for (i, keyframe) in self.keyframes.iter().enumerate().rev() {
|
||||
if keyframe.read_with(guard).selector == selector {
|
||||
return Some(i);
|
||||
|
@ -120,7 +123,7 @@ impl KeyframePercentage {
|
|||
KeyframePercentage(value)
|
||||
}
|
||||
|
||||
fn parse(input: &mut Parser) -> Result<KeyframePercentage, ()> {
|
||||
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<KeyframePercentage, ParseError<'i>> {
|
||||
let percentage = if input.try(|input| input.expect_ident_matching("from")).is_ok() {
|
||||
KeyframePercentage::new(0.)
|
||||
} else if input.try(|input| input.expect_ident_matching("to")).is_ok() {
|
||||
|
@ -130,7 +133,7 @@ impl KeyframePercentage {
|
|||
if percentage >= 0. && percentage <= 1. {
|
||||
KeyframePercentage::new(percentage)
|
||||
} else {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -168,7 +171,7 @@ impl KeyframeSelector {
|
|||
}
|
||||
|
||||
/// Parse a keyframe selector from CSS input.
|
||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.parse_comma_separated(KeyframePercentage::parse)
|
||||
.map(KeyframeSelector)
|
||||
}
|
||||
|
@ -200,8 +203,8 @@ impl ToCssWithGuard for Keyframe {
|
|||
|
||||
impl Keyframe {
|
||||
/// Parse a CSS keyframe.
|
||||
pub fn parse(css: &str, parent_stylesheet: &Stylesheet)
|
||||
-> Result<Arc<Locked<Self>>, ()> {
|
||||
pub fn parse<'i>(css: &'i str, parent_stylesheet: &Stylesheet)
|
||||
-> Result<Arc<Locked<Self>>, ParseError<'i>> {
|
||||
let error_reporter = NullReporter;
|
||||
let context = ParserContext::new(parent_stylesheet.origin,
|
||||
&parent_stylesheet.url_data,
|
||||
|
@ -209,7 +212,8 @@ impl Keyframe {
|
|||
Some(CssRuleType::Keyframe),
|
||||
PARSING_MODE_DEFAULT,
|
||||
parent_stylesheet.quirks_mode);
|
||||
let mut input = Parser::new(css);
|
||||
let mut input = ParserInput::new(css);
|
||||
let mut input = Parser::new(&mut input);
|
||||
|
||||
let mut declarations = SourcePropertyDeclaration::new();
|
||||
let mut rule_parser = KeyframeListParser {
|
||||
|
@ -445,29 +449,31 @@ pub fn parse_keyframe_list(context: &ParserContext, input: &mut Parser, shared_l
|
|||
}
|
||||
|
||||
enum Void {}
|
||||
impl<'a> AtRuleParser for KeyframeListParser<'a> {
|
||||
impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> {
|
||||
type Prelude = Void;
|
||||
type AtRule = Arc<Locked<Keyframe>>;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
}
|
||||
|
||||
impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
||||
impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
|
||||
type Prelude = KeyframeSelector;
|
||||
type QualifiedRule = Arc<Locked<Keyframe>>;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<Self::Prelude, ()> {
|
||||
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result<Self::Prelude, ParseError<'i>> {
|
||||
let start = input.position();
|
||||
match KeyframeSelector::parse(input) {
|
||||
Ok(sel) => Ok(sel),
|
||||
Err(()) => {
|
||||
let message = format!("Invalid keyframe rule: '{}'", input.slice_from(start));
|
||||
log_css_error(input, start, &message, self.context);
|
||||
Err(())
|
||||
Err(e) => {
|
||||
let error = ContextualParseError::InvalidKeyframeRule(input.slice_from(start), e.clone());
|
||||
log_css_error(input, start, error, self.context);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_block(&mut self, prelude: Self::Prelude, input: &mut Parser)
|
||||
-> Result<Self::QualifiedRule, ()> {
|
||||
fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self::QualifiedRule, ParseError<'i>> {
|
||||
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframe));
|
||||
let parser = KeyframeDeclarationParser {
|
||||
context: &context,
|
||||
|
@ -480,12 +486,12 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
|||
Ok(()) => {
|
||||
block.extend(iter.parser.declarations.drain(), Importance::Normal);
|
||||
}
|
||||
Err(range) => {
|
||||
Err(err) => {
|
||||
iter.parser.declarations.clear();
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported keyframe property declaration: '{}'",
|
||||
iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, &context);
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::UnsupportedKeyframePropertyDeclaration(
|
||||
iter.input.slice(err.span), err.error);
|
||||
log_css_error(iter.input, pos, error, &context);
|
||||
}
|
||||
}
|
||||
// `parse_important` is not called here, `!important` is not allowed in keyframe blocks.
|
||||
|
@ -503,22 +509,25 @@ struct KeyframeDeclarationParser<'a, 'b: 'a> {
|
|||
}
|
||||
|
||||
/// Default methods reject all at rules.
|
||||
impl<'a, 'b> AtRuleParser for KeyframeDeclarationParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type AtRule = ();
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeclarationParser for KeyframeDeclarationParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||
type Declaration = ();
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
||||
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||
-> Result<(), ParseError<'i>> {
|
||||
let id = try!(PropertyId::parse(name.into()));
|
||||
match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
|
||||
Ok(()) => {
|
||||
// In case there is still unparsed text in the declaration, we should roll back.
|
||||
input.expect_exhausted()
|
||||
input.expect_exhausted().map_err(|e| e.into())
|
||||
}
|
||||
Err(_) => Err(())
|
||||
Err(_e) => Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ mod stylesheet;
|
|||
pub mod supports_rule;
|
||||
pub mod viewport_rule;
|
||||
|
||||
use cssparser::{parse_one_rule, Parser};
|
||||
use cssparser::{parse_one_rule, Parser, ParserInput};
|
||||
use error_reporting::NullReporter;
|
||||
use parser::{ParserContext, PARSING_MODE_DEFAULT};
|
||||
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
|
@ -234,7 +234,8 @@ impl CssRule {
|
|||
parent_stylesheet.quirks_mode
|
||||
);
|
||||
|
||||
let mut input = Parser::new(css);
|
||||
let mut input = ParserInput::new(css);
|
||||
let mut input = Parser::new(&mut input);
|
||||
|
||||
let mut guard = parent_stylesheet.namespaces.write();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
use {Namespace, Prefix};
|
||||
use counter_style::{parse_counter_style_body, parse_counter_style_name};
|
||||
use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser, SourceLocation};
|
||||
use error_reporting::ContextualParseError;
|
||||
use font_face::parse_font_face_block;
|
||||
use media_queries::{parse_media_query_list, MediaList};
|
||||
use parking_lot::RwLock;
|
||||
|
@ -14,9 +15,12 @@ use parser::{Parse, ParserContext, log_css_error};
|
|||
use properties::parse_property_declaration_list;
|
||||
use selector_parser::{SelectorImpl, SelectorParser};
|
||||
use selectors::SelectorList;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::{Locked, SharedRwLock};
|
||||
use std::borrow::Cow;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use str::starts_with_ignore_ascii_case;
|
||||
use style_traits::{StyleParseError, ParseError};
|
||||
use stylearc::Arc;
|
||||
use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
|
||||
use stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
|
||||
|
@ -132,22 +136,24 @@ fn register_namespace(_: &Namespace) -> Result<(), ()> {
|
|||
Ok(()) // servo doesn't use namespace ids
|
||||
}
|
||||
|
||||
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||
impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||
type Prelude = AtRulePrelude;
|
||||
type AtRule = CssRule;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_prelude(
|
||||
fn parse_prelude<'t>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
input: &mut Parser
|
||||
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
|
||||
name: Cow<'i, str>,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
|
||||
let location = get_location_with_offset(input.current_source_location(),
|
||||
self.context.line_number_offset);
|
||||
match_ignore_ascii_case! { name,
|
||||
match_ignore_ascii_case! { &*name,
|
||||
"import" => {
|
||||
if self.state > State::Imports {
|
||||
self.state = State::Invalid;
|
||||
return Err(()) // "@import must be before any rule but @charset"
|
||||
// "@import must be before any rule but @charset"
|
||||
return Err(StyleParseError::UnexpectedImportRule.into())
|
||||
}
|
||||
|
||||
self.state = State::Imports;
|
||||
|
@ -190,14 +196,16 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
"namespace" => {
|
||||
if self.state > State::Namespaces {
|
||||
self.state = State::Invalid;
|
||||
return Err(()) // "@namespace must be before any rule but @charset and @import"
|
||||
// "@namespace must be before any rule but @charset and @import"
|
||||
return Err(StyleParseError::UnexpectedNamespaceRule.into())
|
||||
}
|
||||
self.state = State::Namespaces;
|
||||
|
||||
let prefix_result = input.try(|input| input.expect_ident());
|
||||
let url = Namespace::from(try!(input.expect_url_or_string()));
|
||||
|
||||
let id = register_namespace(&url)?;
|
||||
let id = register_namespace(&url)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError)?;
|
||||
|
||||
let mut namespaces = self.namespaces.as_mut().unwrap();
|
||||
|
||||
|
@ -222,13 +230,13 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
},
|
||||
// @charset is removed by rust-cssparser if it’s the first rule in the stylesheet
|
||||
// anything left is invalid.
|
||||
"charset" => return Err(()), // (insert appropriate error message)
|
||||
"charset" => return Err(StyleParseError::UnexpectedCharsetRule.into()),
|
||||
_ => {}
|
||||
}
|
||||
// Don't allow starting with an invalid state
|
||||
if self.state > State::Body {
|
||||
self.state = State::Invalid;
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
self.state = State::Body;
|
||||
|
||||
|
@ -242,18 +250,21 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_block(&mut self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CssRule, ()> {
|
||||
fn parse_block<'t>(&mut self, prelude: AtRulePrelude, input: &mut Parser<'i, 't>)
|
||||
-> Result<CssRule, ParseError<'i>> {
|
||||
AtRuleParser::parse_block(&mut self.nested(), prelude, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
|
||||
impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||
type Prelude = SelectorList<SelectorImpl>;
|
||||
type QualifiedRule = CssRule;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
#[inline]
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
|
||||
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
|
||||
-> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
|
||||
self.state = State::Body;
|
||||
|
||||
// "Freeze" the namespace map (no more namespace rules can be parsed
|
||||
|
@ -267,11 +278,11 @@ impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_block(
|
||||
fn parse_block<'t>(
|
||||
&mut self,
|
||||
prelude: SelectorList<SelectorImpl>,
|
||||
input: &mut Parser
|
||||
) -> Result<CssRule, ()> {
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<CssRule, ParseError<'i>> {
|
||||
QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
|
||||
}
|
||||
}
|
||||
|
@ -302,10 +313,11 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> {
|
|||
while let Some(result) = iter.next() {
|
||||
match result {
|
||||
Ok(rule) => rules.push(rule),
|
||||
Err(range) => {
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported rule: '{}'", iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, self.context);
|
||||
Err(err) => {
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::UnsupportedRule(
|
||||
iter.input.slice(err.span), err.error);
|
||||
log_css_error(iter.input, pos, error, self.context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,22 +336,23 @@ fn is_viewport_enabled() -> bool {
|
|||
false // Gecko doesn't support @viewport.
|
||||
}
|
||||
|
||||
impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = AtRulePrelude;
|
||||
type AtRule = CssRule;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_prelude(
|
||||
fn parse_prelude<'t>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
input: &mut Parser
|
||||
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
|
||||
name: Cow<'i, str>,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
|
||||
let location =
|
||||
get_location_with_offset(
|
||||
input.current_source_location(),
|
||||
self.context.line_number_offset
|
||||
);
|
||||
|
||||
match_ignore_ascii_case! { name,
|
||||
match_ignore_ascii_case! { &*name,
|
||||
"media" => {
|
||||
let media_queries = parse_media_query_list(self.context, input);
|
||||
let arc = Arc::new(self.shared_lock.wrap(media_queries));
|
||||
|
@ -355,14 +368,14 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
"counter-style" => {
|
||||
if !cfg!(feature = "gecko") {
|
||||
// Support for this rule is not fully implemented in Servo yet.
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||
}
|
||||
let name = parse_counter_style_name(input)?;
|
||||
// ASCII-case-insensitive matches for "decimal" are already
|
||||
// lower-cased by `parse_counter_style_name`, so we can use ==
|
||||
// here.
|
||||
if name.0 == atom!("decimal") {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(AtRuleType::WithBlock(AtRulePrelude::CounterStyle(name)))
|
||||
},
|
||||
|
@ -370,13 +383,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
if is_viewport_enabled() {
|
||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Viewport))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||
}
|
||||
},
|
||||
"keyframes" | "-webkit-keyframes" | "-moz-keyframes" => {
|
||||
let prefix = if starts_with_ignore_ascii_case(name, "-webkit-") {
|
||||
let prefix = if starts_with_ignore_ascii_case(&*name, "-webkit-") {
|
||||
Some(VendorPrefix::WebKit)
|
||||
} else if starts_with_ignore_ascii_case(name, "-moz-") {
|
||||
} else if starts_with_ignore_ascii_case(&*name, "-moz-") {
|
||||
Some(VendorPrefix::Moz)
|
||||
} else {
|
||||
None
|
||||
|
@ -384,7 +397,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
if cfg!(feature = "servo") &&
|
||||
prefix.as_ref().map_or(false, |p| matches!(*p, VendorPrefix::Moz)) {
|
||||
// Servo should not support @-moz-keyframes.
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||
}
|
||||
let name = KeyframesName::parse(self.context, input)?;
|
||||
|
||||
|
@ -394,7 +407,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
if cfg!(feature = "gecko") {
|
||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Page(location)))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||
}
|
||||
},
|
||||
"-moz-document" => {
|
||||
|
@ -402,18 +415,18 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
let cond = DocumentCondition::parse(self.context, input)?;
|
||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond, location)))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||
}
|
||||
},
|
||||
_ => Err(())
|
||||
_ => Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_block(
|
||||
fn parse_block<'t>(
|
||||
&mut self,
|
||||
prelude: AtRulePrelude,
|
||||
input: &mut Parser
|
||||
) -> Result<CssRule, ()> {
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<CssRule, ParseError<'i>> {
|
||||
match prelude {
|
||||
AtRulePrelude::FontFace(location) => {
|
||||
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFace));
|
||||
|
@ -478,11 +491,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||
type Prelude = SelectorList<SelectorImpl>;
|
||||
type QualifiedRule = CssRule;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
|
||||
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
|
||||
-> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
|
||||
let selector_parser = SelectorParser {
|
||||
stylesheet_origin: self.stylesheet_origin,
|
||||
namespaces: self.context.namespaces.unwrap(),
|
||||
|
@ -491,11 +506,11 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
|||
SelectorList::parse(&selector_parser, input)
|
||||
}
|
||||
|
||||
fn parse_block(
|
||||
fn parse_block<'t>(
|
||||
&mut self,
|
||||
prelude: SelectorList<SelectorImpl>,
|
||||
input: &mut Parser
|
||||
) -> Result<CssRule, ()> {
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<CssRule, ParseError<'i>> {
|
||||
let location = get_location_with_offset(input.current_source_location(),
|
||||
self.context.line_number_offset);
|
||||
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style));
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
use {Prefix, Namespace};
|
||||
use context::QuirksMode;
|
||||
use cssparser::{Parser, RuleListParser};
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use cssparser::{Parser, RuleListParser, ParserInput};
|
||||
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||
use fnv::FnvHashMap;
|
||||
use media_queries::{MediaList, Device};
|
||||
use parking_lot::RwLock;
|
||||
|
@ -110,7 +110,8 @@ impl Stylesheet {
|
|||
line_number_offset: u64
|
||||
) -> (Vec<CssRule>, bool) {
|
||||
let mut rules = Vec::new();
|
||||
let mut input = Parser::new(css);
|
||||
let mut input = ParserInput::new(css);
|
||||
let mut input = Parser::new(&mut input);
|
||||
|
||||
let context =
|
||||
ParserContext::new_with_line_number_offset(
|
||||
|
@ -140,10 +141,11 @@ impl Stylesheet {
|
|||
while let Some(result) = iter.next() {
|
||||
match result {
|
||||
Ok(rule) => rules.push(rule),
|
||||
Err(range) => {
|
||||
let pos = range.start;
|
||||
let message = format!("Invalid rule: '{}'", iter.input.slice(range));
|
||||
log_css_error(iter.input, pos, &*message, iter.parser.context());
|
||||
Err(err) => {
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::InvalidRule(
|
||||
iter.input.slice(err.span), err.error);
|
||||
log_css_error(iter.input, pos, error, iter.parser.context());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
|
||||
//! [@supports rules](https://drafts.csswg.org/css-conditional-3/#at-supports)
|
||||
|
||||
use cssparser::{BasicParseError, ParseError as CssParseError, ParserInput};
|
||||
use cssparser::{Delimiter, parse_important, Parser, SourceLocation, Token};
|
||||
use parser::ParserContext;
|
||||
use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use stylearc::Arc;
|
||||
use stylesheets::{CssRuleType, CssRules};
|
||||
|
||||
|
@ -81,7 +83,7 @@ impl SupportsCondition {
|
|||
/// Parse a condition
|
||||
///
|
||||
/// https://drafts.csswg.org/css-conditional/#supports_condition
|
||||
pub fn parse(input: &mut Parser) -> Result<SupportsCondition, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
|
||||
if let Ok(_) = input.try(|i| i.expect_ident_matching("not")) {
|
||||
let inner = SupportsCondition::parse_in_parens(input)?;
|
||||
return Ok(SupportsCondition::Not(Box::new(inner)));
|
||||
|
@ -90,7 +92,7 @@ impl SupportsCondition {
|
|||
let in_parens = SupportsCondition::parse_in_parens(input)?;
|
||||
|
||||
let (keyword, wrapper) = match input.next() {
|
||||
Err(()) => {
|
||||
Err(_) => {
|
||||
// End of input
|
||||
return Ok(in_parens)
|
||||
}
|
||||
|
@ -98,10 +100,10 @@ impl SupportsCondition {
|
|||
match_ignore_ascii_case! { &ident,
|
||||
"and" => ("and", SupportsCondition::And as fn(_) -> _),
|
||||
"or" => ("or", SupportsCondition::Or as fn(_) -> _),
|
||||
_ => return Err(())
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into())
|
||||
}
|
||||
}
|
||||
_ => return Err(())
|
||||
Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
|
||||
};
|
||||
|
||||
let mut conditions = Vec::with_capacity(2);
|
||||
|
@ -118,7 +120,7 @@ impl SupportsCondition {
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens
|
||||
fn parse_in_parens(input: &mut Parser) -> Result<SupportsCondition, ()> {
|
||||
fn parse_in_parens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
|
||||
// Whitespace is normally taken care of in `Parser::next`,
|
||||
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
|
||||
while input.try(Parser::expect_whitespace).is_ok() {}
|
||||
|
@ -127,17 +129,18 @@ impl SupportsCondition {
|
|||
Token::ParenthesisBlock => {
|
||||
input.parse_nested_block(|input| {
|
||||
// `input.try()` not needed here since the alternative uses `consume_all()`.
|
||||
parse_condition_or_declaration(input).or_else(|()| {
|
||||
parse_condition_or_declaration(input).or_else(|_| {
|
||||
consume_all(input);
|
||||
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
|
||||
})
|
||||
})
|
||||
}
|
||||
Token::Function(_) => {
|
||||
input.parse_nested_block(|i| Ok(consume_all(i))).unwrap();
|
||||
let result: Result<_, ParseError> = input.parse_nested_block(|i| Ok(consume_all(i)));
|
||||
result.unwrap();
|
||||
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
|
||||
}
|
||||
_ => Err(())
|
||||
t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +159,8 @@ impl SupportsCondition {
|
|||
|
||||
/// supports_condition | declaration
|
||||
/// https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext
|
||||
pub fn parse_condition_or_declaration(input: &mut Parser) -> Result<SupportsCondition, ()> {
|
||||
pub fn parse_condition_or_declaration<'i, 't>(input: &mut Parser<'i, 't>)
|
||||
-> Result<SupportsCondition, ParseError<'i>> {
|
||||
if let Ok(condition) = input.try(SupportsCondition::parse) {
|
||||
Ok(SupportsCondition::Parenthesized(Box::new(condition)))
|
||||
} else {
|
||||
|
@ -244,7 +248,7 @@ fn consume_all(input: &mut Parser) {
|
|||
|
||||
impl Declaration {
|
||||
/// Parse a declaration
|
||||
pub fn parse(input: &mut Parser) -> Result<Declaration, ()> {
|
||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Declaration, ParseError<'i>> {
|
||||
let prop = input.expect_ident()?.into_owned();
|
||||
input.expect_colon()?;
|
||||
let val = parse_anything(input);
|
||||
|
@ -260,12 +264,13 @@ impl Declaration {
|
|||
} else {
|
||||
return false
|
||||
};
|
||||
let mut input = Parser::new(&self.val);
|
||||
let mut input = ParserInput::new(&self.val);
|
||||
let mut input = Parser::new(&mut input);
|
||||
let context = ParserContext::new_with_rule_type(cx, Some(CssRuleType::Style));
|
||||
let mut declarations = SourcePropertyDeclaration::new();
|
||||
let res = input.parse_until_before(Delimiter::Bang, |input| {
|
||||
PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
|
||||
.map_err(|_| ())
|
||||
.map_err(|e| StyleParseError::PropertyDeclaration(e).into())
|
||||
});
|
||||
let _ = input.try(parse_important);
|
||||
res.is_ok() && input.is_exhausted()
|
||||
|
|
|
@ -11,18 +11,20 @@ use app_units::Au;
|
|||
use context::QuirksMode;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
||||
use cssparser::ToCss as ParserToCss;
|
||||
use error_reporting::ContextualParseError;
|
||||
use euclid::size::TypedSize2D;
|
||||
use font_metrics::get_metrics_provider_for_product;
|
||||
use media_queries::Device;
|
||||
use parser::{Parse, ParserContext, log_css_error};
|
||||
use properties::StyleBuilder;
|
||||
use selectors::parser::SelectorParseError;
|
||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::iter::Enumerate;
|
||||
use std::str::Chars;
|
||||
use style_traits::{PinchZoomFactor, ToCss};
|
||||
use style_traits::{PinchZoomFactor, ToCss, ParseError, StyleParseError};
|
||||
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
|
||||
use stylearc::Arc;
|
||||
use stylesheets::{Stylesheet, Origin};
|
||||
|
@ -167,7 +169,8 @@ impl FromMeta for ViewportLength {
|
|||
}
|
||||
|
||||
impl ViewportLength {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
// we explicitly do not accept 'extend-to-zoom', since it is a UA
|
||||
// internal value for <META> viewport translation
|
||||
LengthOrPercentageOrAuto::parse_non_negative(context, input).map(ViewportLength::Specified)
|
||||
|
@ -246,23 +249,27 @@ impl ToCss for ViewportDescriptorDeclaration {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_shorthand(context: &ParserContext, input: &mut Parser) -> Result<(ViewportLength, ViewportLength), ()> {
|
||||
fn parse_shorthand<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<(ViewportLength, ViewportLength), ParseError<'i>> {
|
||||
let min = try!(ViewportLength::parse(context, input));
|
||||
match input.try(|i| ViewportLength::parse(context, i)) {
|
||||
Err(()) => Ok((min.clone(), min)),
|
||||
Err(_) => Ok((min.clone(), min)),
|
||||
Ok(max) => Ok((min, max))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> AtRuleParser for ViewportRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||
type Prelude = ();
|
||||
type AtRule = Vec<ViewportDescriptorDeclaration>;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
}
|
||||
|
||||
impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
||||
impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||
type Declaration = Vec<ViewportDescriptorDeclaration>;
|
||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||
|
||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Vec<ViewportDescriptorDeclaration>, ()> {
|
||||
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||
-> Result<Vec<ViewportDescriptorDeclaration>, ParseError<'i>> {
|
||||
macro_rules! declaration {
|
||||
($declaration:ident($parse:expr)) => {
|
||||
declaration!($declaration(value: try!($parse(input)),
|
||||
|
@ -289,7 +296,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
|||
}}
|
||||
}
|
||||
|
||||
match_ignore_ascii_case! { name,
|
||||
match_ignore_ascii_case! { &*name,
|
||||
"min-width" => ok!(MinWidth(|i| ViewportLength::parse(self.context, i))),
|
||||
"max-width" => ok!(MaxWidth(|i| ViewportLength::parse(self.context, i))),
|
||||
"width" => ok!(shorthand -> [MinWidth, MaxWidth]),
|
||||
|
@ -301,7 +308,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
|||
"max-zoom" => ok!(MaxZoom(Zoom::parse)),
|
||||
"user-zoom" => ok!(UserZoom(UserZoom::parse)),
|
||||
"orientation" => ok!(Orientation(Orientation::parse)),
|
||||
_ => Err(()),
|
||||
_ => Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +335,7 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
|
|||
}
|
||||
|
||||
impl Parse for ViewportRule {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let parser = ViewportRuleParser { context: context };
|
||||
|
||||
let mut cascade = Cascade::new();
|
||||
|
@ -340,11 +347,11 @@ impl Parse for ViewportRule {
|
|||
cascade.add(Cow::Owned(declarations))
|
||||
}
|
||||
}
|
||||
Err(range) => {
|
||||
let pos = range.start;
|
||||
let message = format!("Unsupported @viewport descriptor declaration: '{}'",
|
||||
parser.input.slice(range));
|
||||
log_css_error(parser.input, pos, &*message, &context);
|
||||
Err(err) => {
|
||||
let pos = err.span.start;
|
||||
let error = ContextualParseError::UnsupportedViewportDescriptorDeclaration(
|
||||
parser.input.slice(err.span), err.error);
|
||||
log_css_error(parser.input, pos, error, &context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use context::{QuirksMode, SharedStyleContext};
|
|||
use data::ComputedStyle;
|
||||
use dom::TElement;
|
||||
use element_state::ElementState;
|
||||
use error_reporting::RustLogReporter;
|
||||
use error_reporting::create_error_reporter;
|
||||
use font_metrics::FontMetricsProvider;
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::{nsIAtom, StyleRuleInclusion};
|
||||
|
@ -595,7 +595,7 @@ impl Stylist {
|
|||
parent.map(|p| &**p),
|
||||
None,
|
||||
None,
|
||||
&RustLogReporter,
|
||||
&create_error_reporter(),
|
||||
font_metrics,
|
||||
cascade_flags,
|
||||
self.quirks_mode);
|
||||
|
@ -676,7 +676,7 @@ impl Stylist {
|
|||
Some(parent_style),
|
||||
None,
|
||||
None,
|
||||
&RustLogReporter,
|
||||
&create_error_reporter(),
|
||||
font_metrics,
|
||||
CascadeFlags::empty(),
|
||||
self.quirks_mode);
|
||||
|
@ -1216,7 +1216,7 @@ impl Stylist {
|
|||
Some(parent_style),
|
||||
None,
|
||||
None,
|
||||
&RustLogReporter,
|
||||
&create_error_reporter(),
|
||||
&metrics,
|
||||
CascadeFlags::empty(),
|
||||
self.quirks_mode))
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
|
||||
use cssparser::{Parser, serialize_identifier};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::{fmt, mem, usize};
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use values::{CSSFloat, CustomIdent};
|
||||
use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue};
|
||||
use values::specified::Integer;
|
||||
|
@ -70,7 +71,7 @@ impl ToCss for GridLine {
|
|||
}
|
||||
|
||||
impl Parse for GridLine {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let mut grid_line = Default::default();
|
||||
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||
return Ok(grid_line)
|
||||
|
@ -85,7 +86,7 @@ impl Parse for GridLine {
|
|||
for _ in 0..3 { // Maximum possible entities for <grid-line>
|
||||
if input.try(|i| i.expect_ident_matching("span")).is_ok() {
|
||||
if grid_line.is_span {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
if grid_line.line_num.is_some() || grid_line.ident.is_some() {
|
||||
|
@ -95,14 +96,14 @@ impl Parse for GridLine {
|
|||
grid_line.is_span = true;
|
||||
} else if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
|
||||
if i.value() == 0 || val_before_span || grid_line.line_num.is_some() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
grid_line.line_num = Some(i);
|
||||
} else if let Ok(name) = input.try(|i| i.expect_ident()) {
|
||||
if val_before_span || grid_line.ident.is_some() ||
|
||||
CustomIdent::from_ident((&*name).into(), &[]).is_err() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
grid_line.ident = Some(name.into_owned());
|
||||
|
@ -112,18 +113,18 @@ impl Parse for GridLine {
|
|||
}
|
||||
|
||||
if grid_line.is_auto() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
if grid_line.is_span {
|
||||
if let Some(i) = grid_line.line_num {
|
||||
if i.value() <= 0 { // disallow negative integers for grid spans
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
} else if grid_line.ident.is_some() { // integer could be omitted
|
||||
grid_line.line_num = Some(Integer::new(1));
|
||||
} else {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,19 +342,20 @@ pub enum RepeatCount {
|
|||
}
|
||||
|
||||
impl Parse for RepeatCount {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
|
||||
if i.value() > 0 {
|
||||
Ok(RepeatCount::Number(i))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
} else {
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"auto-fill" => Ok(RepeatCount::AutoFill),
|
||||
"auto-fit" => Ok(RepeatCount::AutoFit),
|
||||
_ => Err(()),
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
use counter_style::{Symbols, parse_counter_style_name};
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::fmt;
|
||||
use style_traits::{OneOrMoreCommaSeparated, ToCss};
|
||||
use style_traits::{OneOrMoreCommaSeparated, ToCss, ParseError, StyleParseError};
|
||||
use super::CustomIdent;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
|
@ -79,7 +80,7 @@ impl CounterStyleOrNone {
|
|||
no_viewport_percentage!(CounterStyleOrNone);
|
||||
|
||||
impl Parse for CounterStyleOrNone {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
||||
return Ok(CounterStyleOrNone::Name(name));
|
||||
}
|
||||
|
@ -95,16 +96,16 @@ impl Parse for CounterStyleOrNone {
|
|||
// numeric system.
|
||||
if (symbols_type == SymbolsType::Alphabetic ||
|
||||
symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
// Identifier is not allowed in symbols() function.
|
||||
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
|
||||
});
|
||||
}
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,7 +160,7 @@ impl<T: Parse> Parse for FontSettingTag<T> {
|
|||
/// settings-control-the-font-variation-settings-property
|
||||
/// <string> [ on | off | <integer> ]
|
||||
/// <string> <number>
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
use byteorder::{ReadBytesExt, BigEndian};
|
||||
use std::io::Cursor;
|
||||
|
||||
|
@ -169,7 +170,7 @@ impl<T: Parse> Parse for FontSettingTag<T> {
|
|||
if tag.len() != 4 ||
|
||||
tag.chars().any(|c| c < ' ' || c > '~')
|
||||
{
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
let mut raw = Cursor::new(tag.as_bytes());
|
||||
|
@ -192,7 +193,7 @@ pub enum FontSettings<T> {
|
|||
|
||||
impl<T: Parse> Parse for FontSettings<T> {
|
||||
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(FontSettings::Normal);
|
||||
}
|
||||
|
@ -227,13 +228,13 @@ impl ToCss for FontSettingTagInt {
|
|||
}
|
||||
|
||||
impl Parse for FontSettingTagInt {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(value) = input.try(|input| input.expect_integer()) {
|
||||
// handle integer, throw if it is negative
|
||||
if value >= 0 {
|
||||
Ok(FontSettingTagInt(value as u32))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
|
||||
// on is an alias for '1'
|
||||
|
@ -250,8 +251,8 @@ impl Parse for FontSettingTagInt {
|
|||
|
||||
|
||||
impl Parse for FontSettingTagFloat {
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
input.expect_number().map(FontSettingTagFloat)
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,18 +327,19 @@ impl<ColorType> SVGPaint<ColorType> {
|
|||
|
||||
impl<ColorType> SVGPaintKind<ColorType> {
|
||||
/// Parse a keyword value only
|
||||
fn parse_ident(input: &mut Parser) -> Result<Self, ()> {
|
||||
Ok(match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
"none" => SVGPaintKind::None,
|
||||
"context-fill" => SVGPaintKind::ContextFill,
|
||||
"context-stroke" => SVGPaintKind::ContextStroke,
|
||||
_ => return Err(())
|
||||
})
|
||||
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"none" => Ok(SVGPaintKind::None),
|
||||
"context-fill" => Ok(SVGPaintKind::ContextFill),
|
||||
"context-stroke" => Ok(SVGPaintKind::ContextStroke),
|
||||
_ => Err(())
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
|
||||
let fallback = input.try(|i| ColorType::parse(context, i));
|
||||
Ok(SVGPaint {
|
||||
|
@ -363,7 +365,7 @@ impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
|
|||
fallback: None,
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
|
||||
/// A CSS value made of four components, where its `ToCss` impl will try to
|
||||
/// serialize as few components as possible, like for example in `border-width`.
|
||||
|
@ -26,12 +26,12 @@ impl<T> Rect<T>
|
|||
where T: Clone
|
||||
{
|
||||
/// Parses a new `Rect<T>` value with the given parse function.
|
||||
pub fn parse_with<Parse>(
|
||||
pub fn parse_with<'i, 't, Parse>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
parse: Parse)
|
||||
-> Result<Self, ()>
|
||||
where Parse: Fn(&ParserContext, &mut Parser) -> Result<T, ()>
|
||||
-> Result<Self, ParseError<'i>>
|
||||
where Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>
|
||||
{
|
||||
let first = parse(context, input)?;
|
||||
let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else {
|
||||
|
@ -64,7 +64,7 @@ impl<T> Parse for Rect<T>
|
|||
where T: Clone + Parse
|
||||
{
|
||||
#[inline]
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with(context, input, T::parse)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use cssparser::Parser;
|
|||
use parser::ParserContext;
|
||||
use properties::animated_properties::Animatable;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError};
|
||||
|
||||
/// A generic value for the `initial-letter` property.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -71,12 +71,12 @@ impl<Value> Spacing<Value> {
|
|||
|
||||
/// Parses.
|
||||
#[inline]
|
||||
pub fn parse_with<F>(
|
||||
pub fn parse_with<'i, 't, F>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
parse: F)
|
||||
-> Result<Self, ()>
|
||||
where F: FnOnce(&ParserContext, &mut Parser) -> Result<Value, ()>
|
||||
-> Result<Self, ParseError<'i>>
|
||||
where F: FnOnce(&ParserContext, &mut Parser<'i, 't>) -> Result<Value, ParseError<'i>>
|
||||
{
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(Spacing::Normal);
|
||||
|
|
|
@ -9,13 +9,14 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
use Atom;
|
||||
pub use cssparser::{RGBA, Token, Parser, serialize_identifier};
|
||||
pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::hash;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
|
||||
pub mod computed;
|
||||
pub mod generics;
|
||||
|
@ -54,7 +55,8 @@ impl<A: Debug, B: Debug> Debug for Either<A, B> {
|
|||
}
|
||||
|
||||
impl<A: Parse, B: Parse> Parse for Either<A, B> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Either<A, B>, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Either<A, B>, ParseError<'i>> {
|
||||
if let Ok(v) = input.try(|i| A::parse(context, i)) {
|
||||
Ok(Either::First(v))
|
||||
} else {
|
||||
|
@ -91,13 +93,16 @@ pub struct CustomIdent(pub Atom);
|
|||
|
||||
impl CustomIdent {
|
||||
/// Parse an already-tokenizer identifier
|
||||
pub fn from_ident(ident: Cow<str>, excluding: &[&str]) -> Result<Self, ()> {
|
||||
match_ignore_ascii_case! { &ident,
|
||||
"initial" | "inherit" | "unset" | "default" => return Err(()),
|
||||
_ => {}
|
||||
pub fn from_ident<'i>(ident: Cow<'i, str>, excluding: &[&str]) -> Result<Self, ParseError<'i>> {
|
||||
let valid = match_ignore_ascii_case! { &ident,
|
||||
"initial" | "inherit" | "unset" | "default" => false,
|
||||
_ => true
|
||||
};
|
||||
if !valid {
|
||||
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||
}
|
||||
if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
} else {
|
||||
Ok(CustomIdent(ident.into()))
|
||||
}
|
||||
|
@ -125,7 +130,7 @@ impl KeyframesName {
|
|||
pub fn from_ident(value: String) -> Self {
|
||||
match CustomIdent::from_ident((&*value).into(), &["none"]) {
|
||||
Ok(ident) => KeyframesName::Ident(ident),
|
||||
Err(()) => KeyframesName::QuotedString(value.into()),
|
||||
Err(_) => KeyframesName::QuotedString(value.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,11 +158,12 @@ impl hash::Hash for KeyframesName {
|
|||
}
|
||||
|
||||
impl Parse for KeyframesName {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
match input.next() {
|
||||
Ok(Token::Ident(s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)),
|
||||
Ok(Token::QuotedString(s)) => Ok(KeyframesName::QuotedString(s.into())),
|
||||
_ => Err(())
|
||||
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
use cssparser::Parser;
|
||||
use gecko_bindings::structs;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
|
||||
bitflags! {
|
||||
/// Constants shared by multiple CSS Box Alignment properties
|
||||
|
@ -177,7 +178,7 @@ no_viewport_percentage!(AlignJustifyContent);
|
|||
impl Parse for AlignJustifyContent {
|
||||
// normal | <baseline-position> |
|
||||
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ]
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
// normal | <baseline-position>
|
||||
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) {
|
||||
return Ok(AlignJustifyContent::new(value))
|
||||
|
@ -198,7 +199,7 @@ impl Parse for AlignJustifyContent {
|
|||
}
|
||||
return Ok(AlignJustifyContent::new(fallback))
|
||||
}
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +228,7 @@ no_viewport_percentage!(AlignJustifySelf);
|
|||
impl Parse for AlignJustifySelf {
|
||||
// auto | normal | stretch | <baseline-position> |
|
||||
// [ <overflow-position>? && <self-position> ]
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
// auto | normal | stretch | <baseline-position>
|
||||
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
||||
return Ok(AlignJustifySelf(value))
|
||||
|
@ -236,7 +237,7 @@ impl Parse for AlignJustifySelf {
|
|||
if let Ok(value) = input.try(parse_overflow_self_position) {
|
||||
return Ok(AlignJustifySelf(value))
|
||||
}
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +266,7 @@ no_viewport_percentage!(AlignItems);
|
|||
impl Parse for AlignItems {
|
||||
// normal | stretch | <baseline-position> |
|
||||
// [ <overflow-position>? && <self-position> ]
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
// normal | stretch | <baseline-position>
|
||||
if let Ok(value) = input.try(parse_normal_stretch_baseline) {
|
||||
return Ok(AlignItems(value))
|
||||
|
@ -274,7 +275,7 @@ impl Parse for AlignItems {
|
|||
if let Ok(value) = input.try(parse_overflow_self_position) {
|
||||
return Ok(AlignItems(value))
|
||||
}
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,7 +305,7 @@ impl Parse for JustifyItems {
|
|||
// auto | normal | stretch | <baseline-position> |
|
||||
// [ <overflow-position>? && <self-position> ]
|
||||
// [ legacy && [ left | right | center ] ]
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
// auto | normal | stretch | <baseline-position>
|
||||
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
||||
return Ok(JustifyItems(value))
|
||||
|
@ -317,7 +318,7 @@ impl Parse for JustifyItems {
|
|||
if let Ok(value) = parse_overflow_self_position(input) {
|
||||
return Ok(JustifyItems(value))
|
||||
}
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,72 +337,73 @@ impl From<AlignJustifyContent> for u16 {
|
|||
}
|
||||
|
||||
// auto | normal | stretch | <baseline-position>
|
||||
fn parse_auto_normal_stretch_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_auto_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>)
|
||||
-> Result<AlignFlags, ParseError<'i>> {
|
||||
if let Ok(baseline) = input.try(parse_baseline) {
|
||||
return Ok(baseline);
|
||||
}
|
||||
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"auto" => Ok(ALIGN_AUTO),
|
||||
"normal" => Ok(ALIGN_NORMAL),
|
||||
"stretch" => Ok(ALIGN_STRETCH),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// normal | stretch | <baseline-position>
|
||||
fn parse_normal_stretch_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
if let Ok(baseline) = input.try(parse_baseline) {
|
||||
return Ok(baseline);
|
||||
}
|
||||
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"normal" => Ok(ALIGN_NORMAL),
|
||||
"stretch" => Ok(ALIGN_STRETCH),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// normal | <baseline-position>
|
||||
fn parse_normal_or_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
if let Ok(baseline) = input.try(parse_baseline) {
|
||||
return Ok(baseline);
|
||||
}
|
||||
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"normal" => Ok(ALIGN_NORMAL),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// <baseline-position>
|
||||
fn parse_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"baseline" => Ok(ALIGN_BASELINE),
|
||||
"first" => input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE),
|
||||
"last" => input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE),
|
||||
"first" => return input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE).map_err(|e| e.into()),
|
||||
"last" => return input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE).map_err(|e| e.into()),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// <content-distribution>
|
||||
fn parse_content_distribution(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"stretch" => Ok(ALIGN_STRETCH),
|
||||
"space-between" => Ok(ALIGN_SPACE_BETWEEN),
|
||||
"space-around" => Ok(ALIGN_SPACE_AROUND),
|
||||
"space-evenly" => Ok(ALIGN_SPACE_EVENLY),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// [ <overflow-position>? && <content-position> ]
|
||||
fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_overflow_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
// <content-position> followed by optional <overflow-position>
|
||||
if let Ok(mut content) = input.try(parse_content_position) {
|
||||
if let Ok(overflow) = input.try(parse_overflow_position) {
|
||||
|
@ -415,13 +417,13 @@ fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()>
|
|||
return Ok(overflow | content)
|
||||
}
|
||||
}
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
// <content-position>
|
||||
fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"start" => Ok(ALIGN_START),
|
||||
"end" => Ok(ALIGN_END),
|
||||
"flex-start" => Ok(ALIGN_FLEX_START),
|
||||
|
@ -430,21 +432,21 @@ fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
|||
"left" => Ok(ALIGN_LEFT),
|
||||
"right" => Ok(ALIGN_RIGHT),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// <overflow-position>
|
||||
fn parse_overflow_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"safe" => Ok(ALIGN_SAFE),
|
||||
"unsafe" => Ok(ALIGN_UNSAFE),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// [ <overflow-position>? && <self-position> ]
|
||||
fn parse_overflow_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_overflow_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
// <self-position> followed by optional <overflow-position>
|
||||
if let Ok(mut self_position) = input.try(parse_self_position) {
|
||||
if let Ok(overflow) = input.try(parse_overflow_position) {
|
||||
|
@ -458,13 +460,13 @@ fn parse_overflow_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
|||
return Ok(overflow | self_position)
|
||||
}
|
||||
}
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
// <self-position>
|
||||
fn parse_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { &ident,
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"start" => Ok(ALIGN_START),
|
||||
"end" => Ok(ALIGN_END),
|
||||
"flex-start" => Ok(ALIGN_FLEX_START),
|
||||
|
@ -475,28 +477,28 @@ fn parse_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
|||
"self-start" => Ok(ALIGN_SELF_START),
|
||||
"self-end" => Ok(ALIGN_SELF_END),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
|
||||
// [ legacy && [ left | right | center ] ]
|
||||
fn parse_legacy(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||
let a = input.expect_ident()?;
|
||||
let b = input.expect_ident()?;
|
||||
if a.eq_ignore_ascii_case("legacy") {
|
||||
match_ignore_ascii_case! { &b,
|
||||
(match_ignore_ascii_case! { &b,
|
||||
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
|
||||
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
|
||||
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(b).into())
|
||||
} else if b.eq_ignore_ascii_case("legacy") {
|
||||
match_ignore_ascii_case! { &a,
|
||||
(match_ignore_ascii_case! { &a,
|
||||
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
|
||||
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
|
||||
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(a).into())
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use style_traits::ParseError;
|
||||
use values::generics::background::BackgroundSize as GenericBackgroundSize;
|
||||
use values::specified::length::LengthOrPercentageOrAuto;
|
||||
|
||||
|
@ -13,17 +15,18 @@ use values::specified::length::LengthOrPercentageOrAuto;
|
|||
pub type BackgroundSize = GenericBackgroundSize<LengthOrPercentageOrAuto>;
|
||||
|
||||
impl Parse for BackgroundSize {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(width) = input.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i)) {
|
||||
let height = input
|
||||
.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i))
|
||||
.unwrap_or(LengthOrPercentageOrAuto::Auto);
|
||||
return Ok(GenericBackgroundSize::Explicit { width: width, height: height });
|
||||
}
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"cover" => Ok(GenericBackgroundSize::Cover),
|
||||
"contain" => Ok(GenericBackgroundSize::Contain),
|
||||
_ => Err(()),
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use values::generics::basic_shape::{Circle as GenericCircle};
|
||||
use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse};
|
||||
use values::generics::basic_shape::{FillRule, BasicShape as GenericBasicShape};
|
||||
|
@ -49,7 +50,7 @@ pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;
|
|||
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
||||
|
||||
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(ShapeSource::None)
|
||||
}
|
||||
|
@ -80,42 +81,43 @@ impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
|
|||
return Ok(ShapeSource::Shape(shp, ref_box))
|
||||
}
|
||||
|
||||
ref_box.map(|v| ShapeSource::Box(v)).ok_or(())
|
||||
ref_box.map(|v| ShapeSource::Box(v)).ok_or(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for GeometryBox {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
|
||||
return Ok(GeometryBox::ShapeBox(shape_box))
|
||||
}
|
||||
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"fill-box" => Ok(GeometryBox::FillBox),
|
||||
"stroke-box" => Ok(GeometryBox::StrokeBox),
|
||||
"view-box" => Ok(GeometryBox::ViewBox),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for BasicShape {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let function = input.expect_function()?;
|
||||
input.parse_nested_block(|i| {
|
||||
match_ignore_ascii_case! { &function,
|
||||
"inset" => InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
|
||||
"circle" => Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
|
||||
"ellipse" => Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
|
||||
"polygon" => Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
|
||||
input.parse_nested_block(move |i| {
|
||||
(match_ignore_ascii_case! { &function,
|
||||
"inset" => return InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
|
||||
"circle" => return Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
|
||||
"ellipse" => return Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
|
||||
"polygon" => return Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for InsetRect {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.expect_function_matching("inset")?;
|
||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||
}
|
||||
|
@ -123,7 +125,8 @@ impl Parse for InsetRect {
|
|||
|
||||
impl InsetRect {
|
||||
/// Parse the inner function arguments of `inset()`
|
||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let rect = Rect::parse_with(context, input, LengthOrPercentage::parse)?;
|
||||
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
|
||||
Some(BorderRadius::parse(context, input)?)
|
||||
|
@ -138,7 +141,8 @@ impl InsetRect {
|
|||
}
|
||||
|
||||
impl Parse for Circle {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
input.expect_function_matching("circle")?;
|
||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||
}
|
||||
|
@ -146,7 +150,8 @@ impl Parse for Circle {
|
|||
|
||||
impl Circle {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_default();
|
||||
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
||||
Position::parse(context, input)?
|
||||
|
@ -176,7 +181,7 @@ impl ToCss for Circle {
|
|||
}
|
||||
|
||||
impl Parse for Ellipse {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.expect_function_matching("ellipse")?;
|
||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||
}
|
||||
|
@ -184,8 +189,9 @@ impl Parse for Ellipse {
|
|||
|
||||
impl Ellipse {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
let (a, b) = input.try(|i| -> Result<_, ()> {
|
||||
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let (a, b) = input.try(|i| -> Result<_, ParseError> {
|
||||
Ok((ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?))
|
||||
}).ok().unwrap_or_default();
|
||||
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
||||
|
@ -219,16 +225,18 @@ impl ToCss for Ellipse {
|
|||
}
|
||||
|
||||
impl Parse for ShapeRadius {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||
return Ok(GenericShapeRadius::Length(lop))
|
||||
}
|
||||
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"closest-side" => Ok(GenericShapeRadius::ClosestSide),
|
||||
"farthest-side" => Ok(GenericShapeRadius::FarthestSide),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +308,7 @@ fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) -> fmt::R
|
|||
}
|
||||
|
||||
impl Parse for Polygon {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.expect_function_matching("polygon")?;
|
||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||
}
|
||||
|
@ -308,8 +316,9 @@ impl Parse for Polygon {
|
|||
|
||||
impl Polygon {
|
||||
/// Parse the inner arguments of a `polygon` function.
|
||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
let fill = input.try(|i| -> Result<_, ()> {
|
||||
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let fill = input.try(|i| -> Result<_, ParseError> {
|
||||
let fill = FillRule::parse(i)?;
|
||||
i.expect_comma()?; // only eat the comma if there is something before it
|
||||
Ok(fill)
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use style_traits::ParseError;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
||||
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
|
||||
|
@ -47,26 +49,27 @@ pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
|
|||
|
||||
impl BorderSideWidth {
|
||||
/// Parses, with quirks.
|
||||
pub fn parse_quirky(
|
||||
pub fn parse_quirky<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()>
|
||||
-> Result<Self, ParseError<'i>>
|
||||
{
|
||||
if let Ok(length) = input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
|
||||
return Ok(BorderSideWidth::Length(length));
|
||||
}
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
let ident = input.expect_ident()?;
|
||||
(match_ignore_ascii_case! { &ident,
|
||||
"thin" => Ok(BorderSideWidth::Thin),
|
||||
"medium" => Ok(BorderSideWidth::Medium),
|
||||
"thick" => Ok(BorderSideWidth::Thick),
|
||||
_ => Err(())
|
||||
}
|
||||
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for BorderSideWidth {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +105,7 @@ impl BorderImageSideWidth {
|
|||
}
|
||||
|
||||
impl Parse for BorderImageSideWidth {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||
return Ok(GenericBorderImageSideWidth::Auto);
|
||||
}
|
||||
|
@ -117,7 +120,7 @@ impl Parse for BorderImageSideWidth {
|
|||
}
|
||||
|
||||
impl Parse for BorderImageSlice {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let mut fill = input.try(|i| i.expect_ident_matching("fill")).is_ok();
|
||||
let offsets = Rect::parse_with(context, input, NumberOrPercentage::parse_non_negative)?;
|
||||
if !fill {
|
||||
|
@ -131,7 +134,7 @@ impl Parse for BorderImageSlice {
|
|||
}
|
||||
|
||||
impl Parse for BorderRadius {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?;
|
||||
let heights = if input.try(|i| i.expect_delim('/')).is_ok() {
|
||||
Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?
|
||||
|
@ -149,11 +152,11 @@ impl Parse for BorderRadius {
|
|||
}
|
||||
|
||||
impl Parse for BorderCornerRadius {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let first = LengthOrPercentage::parse_non_negative(context, input)?;
|
||||
let second = input
|
||||
.try(|i| LengthOrPercentage::parse_non_negative(context, i))
|
||||
.unwrap_or_else(|()| first.clone());
|
||||
.unwrap_or_else(|_| first.clone());
|
||||
Ok(Self::new(first, second))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::{Parser, Token};
|
||||
use cssparser::{Parser, Token, BasicParseError};
|
||||
use parser::ParserContext;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
|
||||
use style_traits::values::specified::AllowedLengthType;
|
||||
use values::{CSSInteger, CSSFloat};
|
||||
use values::specified::{Angle, Time};
|
||||
|
@ -142,11 +142,11 @@ impl CalcNode {
|
|||
///
|
||||
/// May return a "complex" `CalcNode`, in the presence of a parenthesized
|
||||
/// expression, for example.
|
||||
fn parse_one(
|
||||
fn parse_one<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
expected_unit: CalcUnit)
|
||||
-> Result<Self, ()>
|
||||
-> Result<Self, ParseError<'i>>
|
||||
{
|
||||
match (try!(input.next()), expected_unit) {
|
||||
(Token::Number(ref value), _) => Ok(CalcNode::Number(value.value)),
|
||||
|
@ -154,18 +154,21 @@ impl CalcNode {
|
|||
(Token::Dimension(ref value, ref unit), CalcUnit::LengthOrPercentage) => {
|
||||
NoCalcLength::parse_dimension(context, value.value, unit)
|
||||
.map(CalcNode::Length)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
(Token::Dimension(ref value, ref unit), CalcUnit::Angle) => {
|
||||
Angle::parse_dimension(value.value,
|
||||
unit,
|
||||
/* from_calc = */ true)
|
||||
.map(CalcNode::Angle)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
(Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
|
||||
Time::parse_dimension(value.value,
|
||||
unit,
|
||||
/* from_calc = */ true)
|
||||
.map(CalcNode::Time)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
(Token::Percentage(ref value), CalcUnit::LengthOrPercentage) => {
|
||||
Ok(CalcNode::Percentage(value.unit_value))
|
||||
|
@ -180,18 +183,18 @@ impl CalcNode {
|
|||
CalcNode::parse(context, i, expected_unit)
|
||||
})
|
||||
}
|
||||
_ => Err(())
|
||||
(t, _) => Err(BasicParseError::UnexpectedToken(t).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a top-level `calc` expression, with all nested sub-expressions.
|
||||
///
|
||||
/// This is in charge of parsing, for example, `2 + 3 * 100%`.
|
||||
fn parse(
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
expected_unit: CalcUnit)
|
||||
-> Result<Self, ()>
|
||||
-> Result<Self, ParseError<'i>>
|
||||
{
|
||||
let mut root = Self::parse_product(context, input, expected_unit)?;
|
||||
|
||||
|
@ -217,7 +220,7 @@ impl CalcNode {
|
|||
CalcNode::Sub(Box::new(root), Box::new(rhs));
|
||||
root = new_root;
|
||||
}
|
||||
_ => return Err(()),
|
||||
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -239,11 +242,11 @@ impl CalcNode {
|
|||
/// * `2 * 2`
|
||||
/// * `2 * 2 + 2` (but will leave the `+ 2` unparsed).
|
||||
///
|
||||
fn parse_product(
|
||||
fn parse_product<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
expected_unit: CalcUnit)
|
||||
-> Result<Self, ()>
|
||||
-> Result<Self, ParseError<'i>>
|
||||
{
|
||||
let mut root = Self::parse_one(context, input, expected_unit)?;
|
||||
|
||||
|
@ -491,65 +494,71 @@ impl CalcNode {
|
|||
}
|
||||
|
||||
/// Convenience parsing function for integers.
|
||||
pub fn parse_integer(
|
||||
pub fn parse_integer<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<CSSInteger, ()>
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<CSSInteger, ParseError<'i>>
|
||||
{
|
||||
Self::parse(context, input, CalcUnit::Integer)?
|
||||
.to_number()
|
||||
.map(|n| n as CSSInteger)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<length> | <percentage>`.
|
||||
pub fn parse_length_or_percentage(
|
||||
pub fn parse_length_or_percentage<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
clamping_mode: AllowedLengthType)
|
||||
-> Result<CalcLengthOrPercentage, ()>
|
||||
-> Result<CalcLengthOrPercentage, ParseError<'i>>
|
||||
{
|
||||
Self::parse(context, input, CalcUnit::LengthOrPercentage)?
|
||||
.to_length_or_percentage(clamping_mode)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<length>`.
|
||||
pub fn parse_length(
|
||||
pub fn parse_length<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
input: &mut Parser<'i, 't>,
|
||||
clamping_mode: AllowedLengthType)
|
||||
-> Result<CalcLengthOrPercentage, ()>
|
||||
-> Result<CalcLengthOrPercentage, ParseError<'i>>
|
||||
{
|
||||
Self::parse(context, input, CalcUnit::Length)?
|
||||
.to_length_or_percentage(clamping_mode)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<number>`.
|
||||
pub fn parse_number(
|
||||
pub fn parse_number<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<CSSFloat, ()>
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<CSSFloat, ParseError<'i>>
|
||||
{
|
||||
Self::parse(context, input, CalcUnit::Number)?
|
||||
.to_number()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<angle>`.
|
||||
pub fn parse_angle(
|
||||
pub fn parse_angle<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<Angle, ()>
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<Angle, ParseError<'i>>
|
||||
{
|
||||
Self::parse(context, input, CalcUnit::Angle)?
|
||||
.to_angle()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<time>`.
|
||||
pub fn parse_time(
|
||||
pub fn parse_time<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<Time, ()>
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<Time, ParseError<'i>>
|
||||
{
|
||||
Self::parse(context, input, CalcUnit::Time)?
|
||||
.to_time()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! Specified color values.
|
||||
|
||||
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token};
|
||||
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token, BasicParseError};
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::nscolor;
|
||||
use itoa;
|
||||
|
@ -13,7 +13,7 @@ use parser::{ParserContext, Parse};
|
|||
use properties::longhands::color::SystemColor;
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use super::AllowQuirks;
|
||||
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
||||
|
||||
|
@ -66,7 +66,7 @@ impl From<RGBA> for Color {
|
|||
}
|
||||
|
||||
impl Parse for Color {
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
// Currently we only store authored value for color keywords,
|
||||
// because all browsers serialize those values as keywords for
|
||||
// specified value.
|
||||
|
@ -93,7 +93,7 @@ impl Parse for Color {
|
|||
}
|
||||
}
|
||||
#[cfg(not(feature = "gecko"))] {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,13 +157,13 @@ impl Color {
|
|||
/// Parse a color, with quirks.
|
||||
///
|
||||
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
input.try(|i| Self::parse(context, i)).or_else(|_| {
|
||||
if !allow_quirks.allowed(context.quirks_mode) {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba))
|
||||
})
|
||||
|
@ -172,7 +172,7 @@ impl Color {
|
|||
/// Parse a <quirky-color> value.
|
||||
///
|
||||
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
||||
fn parse_quirky_color(input: &mut Parser) -> Result<RGBA, ()> {
|
||||
fn parse_quirky_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<RGBA, ParseError<'i>> {
|
||||
let (number, dimension) = match input.next()? {
|
||||
Token::Number(number) => {
|
||||
(number, None)
|
||||
|
@ -182,17 +182,18 @@ impl Color {
|
|||
},
|
||||
Token::Ident(ident) => {
|
||||
if ident.len() != 3 && ident.len() != 6 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
return parse_hash_color(ident.as_bytes());
|
||||
return parse_hash_color(ident.as_bytes())
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
_ => {
|
||||
return Err(());
|
||||
t => {
|
||||
return Err(BasicParseError::UnexpectedToken(t).into());
|
||||
},
|
||||
};
|
||||
let value = number.int_value.ok_or(())?;
|
||||
let value = number.int_value.ok_or(StyleParseError::UnspecifiedError)?;
|
||||
if value < 0 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
let length = if value <= 9 {
|
||||
1
|
||||
|
@ -207,11 +208,11 @@ impl Color {
|
|||
} else if value <= 999999 {
|
||||
6
|
||||
} else {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
};
|
||||
let total = length + dimension.as_ref().map_or(0, |d| d.len());
|
||||
if total > 6 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
let mut serialization = [b'0'; 6];
|
||||
let space_padding = 6 - total;
|
||||
|
@ -221,7 +222,7 @@ impl Color {
|
|||
written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap();
|
||||
}
|
||||
debug_assert!(written == 6);
|
||||
parse_hash_color(&serialization)
|
||||
parse_hash_color(&serialization).map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Returns false if the color is completely transparent, and
|
||||
|
@ -306,7 +307,7 @@ pub struct RGBAColor(pub Color);
|
|||
no_viewport_percentage!(RGBAColor);
|
||||
|
||||
impl Parse for RGBAColor {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Color::parse(context, input).map(RGBAColor)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use style_traits::ParseError;
|
||||
use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
|
||||
use values::specified::length::LengthOrPercentage;
|
||||
|
||||
|
@ -13,7 +14,7 @@ use values::specified::length::LengthOrPercentage;
|
|||
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
|
||||
|
||||
impl Parse for ScrollSnapPoint {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(GenericScrollSnapPoint::None);
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
//! CSS handling for the computed value of
|
||||
//! [grids](https://drafts.csswg.org/css-grid/)
|
||||
|
||||
use cssparser::{Parser, Token};
|
||||
use cssparser::{Parser, Token, BasicParseError};
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::{mem, usize};
|
||||
use std::ascii::AsciiExt;
|
||||
use style_traits::HasViewportPercentage;
|
||||
use style_traits::{HasViewportPercentage, ParseError, StyleParseError};
|
||||
use values::{CSSFloat, CustomIdent, Either};
|
||||
use values::computed::{self, Context, ToComputedValue};
|
||||
use values::generics::grid::{RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
|
||||
|
@ -17,16 +17,16 @@ use values::generics::grid::{TrackSize, TrackList, TrackListType};
|
|||
use values::specified::LengthOrPercentage;
|
||||
|
||||
/// Parse a single flexible length.
|
||||
pub fn parse_flex(input: &mut Parser) -> Result<CSSFloat, ()> {
|
||||
pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseError<'i>> {
|
||||
match input.next()? {
|
||||
Token::Dimension(ref value, ref unit) if unit.eq_ignore_ascii_case("fr") && value.value.is_sign_positive()
|
||||
=> Ok(value.value),
|
||||
_ => Err(()),
|
||||
t => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for TrackBreadth<LengthOrPercentage> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||
return Ok(TrackBreadth::Breadth(lop))
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ impl HasViewportPercentage for TrackBreadth<LengthOrPercentage> {
|
|||
}
|
||||
|
||||
impl Parse for TrackSize<LengthOrPercentage> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(b) = input.try(|i| TrackBreadth::parse(context, i)) {
|
||||
return Ok(TrackSize::Breadth(b))
|
||||
}
|
||||
|
@ -81,13 +81,13 @@ impl Parse for TrackSize<LengthOrPercentage> {
|
|||
/// Parse the grid line names into a vector of owned strings.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-grid/#typedef-line-names
|
||||
pub fn parse_line_names(input: &mut Parser) -> Result<Vec<String>, ()> {
|
||||
pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Vec<String>, ParseError<'i>> {
|
||||
input.expect_square_bracket_block()?;
|
||||
input.parse_nested_block(|input| {
|
||||
let mut values = vec![];
|
||||
while let Ok(ident) = input.try(|i| i.expect_ident()) {
|
||||
if CustomIdent::from_ident((&*ident).into(), &["span"]).is_err() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
values.push(ident.into_owned());
|
||||
|
@ -112,9 +112,10 @@ enum RepeatType {
|
|||
}
|
||||
|
||||
impl TrackRepeat<LengthOrPercentage> {
|
||||
fn parse_with_repeat_type(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<(TrackRepeat<LengthOrPercentage>, RepeatType), ()> {
|
||||
input.try(|i| i.expect_function_matching("repeat")).and_then(|_| {
|
||||
fn parse_with_repeat_type<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<(TrackRepeat<LengthOrPercentage>, RepeatType),
|
||||
ParseError<'i>> {
|
||||
input.try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())).and_then(|_| {
|
||||
input.parse_nested_block(|input| {
|
||||
let count = RepeatCount::parse(context, input)?;
|
||||
input.expect_comma()?;
|
||||
|
@ -135,7 +136,8 @@ impl TrackRepeat<LengthOrPercentage> {
|
|||
if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) {
|
||||
if !track_size.is_fixed() {
|
||||
if is_auto {
|
||||
return Err(()) // should be <fixed-size> for <auto-repeat>
|
||||
// should be <fixed-size> for <auto-repeat>
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
if repeat_type == RepeatType::Fixed {
|
||||
|
@ -147,7 +149,8 @@ impl TrackRepeat<LengthOrPercentage> {
|
|||
names.push(current_names);
|
||||
} else {
|
||||
if values.is_empty() {
|
||||
return Err(()) // expecting at least one <track-size>
|
||||
// expecting at least one <track-size>
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
names.push(current_names); // final `<line-names>`
|
||||
|
@ -181,7 +184,7 @@ impl HasViewportPercentage for TrackRepeat<LengthOrPercentage> {
|
|||
pub type TrackSizeOrRepeat = Either<TrackSize<LengthOrPercentage>, TrackRepeat<LengthOrPercentage>>;
|
||||
|
||||
impl Parse for TrackList<TrackSizeOrRepeat> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let mut current_names;
|
||||
let mut names = vec![];
|
||||
let mut values = vec![];
|
||||
|
@ -198,7 +201,8 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
|
|||
if !track_size.is_fixed() {
|
||||
atleast_one_not_fixed = true;
|
||||
if is_auto {
|
||||
return Err(()) // <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
|
||||
// <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,13 +217,13 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
|
|||
RepeatType::Normal => {
|
||||
atleast_one_not_fixed = true;
|
||||
if is_auto { // only <fixed-repeat>
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
},
|
||||
RepeatType::Auto => {
|
||||
if is_auto || atleast_one_not_fixed {
|
||||
// We've either seen <auto-repeat> earlier, or there's at least one non-fixed value
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
is_auto = true;
|
||||
|
@ -232,7 +236,7 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
|
|||
values.push(Either::Second(repeat));
|
||||
} else {
|
||||
if values.is_empty() {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
names.push(current_names);
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||
|
||||
use Atom;
|
||||
use cssparser::{Parser, Token};
|
||||
use cssparser::{Parser, Token, BasicParseError};
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
#[cfg(feature = "servo")]
|
||||
use servo_url::ServoUrl;
|
||||
use std::cmp::Ordering;
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use values::{Either, None_};
|
||||
use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop};
|
||||
use values::generics::image::{EndingShape as GenericEndingShape, Gradient as GenericGradient};
|
||||
|
@ -82,7 +83,7 @@ pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>;
|
|||
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
||||
|
||||
impl Parse for Image {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Image, ParseError<'i>> {
|
||||
#[cfg(feature = "gecko")]
|
||||
{
|
||||
if let Ok(mut url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||
|
@ -132,53 +133,59 @@ impl Image {
|
|||
}
|
||||
|
||||
/// Parses a `-moz-element(# <element-id>)`.
|
||||
fn parse_element(input: &mut Parser) -> Result<Atom, ()> {
|
||||
fn parse_element<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Atom, ParseError<'i>> {
|
||||
input.try(|i| i.expect_function_matching("-moz-element"))?;
|
||||
input.parse_nested_block(|i| {
|
||||
match i.next()? {
|
||||
Token::IDHash(id) => Ok(Atom::from(id)),
|
||||
_ => Err(()),
|
||||
t => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Gradient {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
enum Shape {
|
||||
Linear,
|
||||
Radial,
|
||||
}
|
||||
|
||||
let (shape, repeating, compat_mode) = match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||
let func = try!(input.expect_function());
|
||||
let result = match_ignore_ascii_case! { &func,
|
||||
"linear-gradient" => {
|
||||
(Shape::Linear, false, CompatMode::Modern)
|
||||
Some((Shape::Linear, false, CompatMode::Modern))
|
||||
},
|
||||
"-webkit-linear-gradient" => {
|
||||
(Shape::Linear, false, CompatMode::WebKit)
|
||||
Some((Shape::Linear, false, CompatMode::WebKit))
|
||||
},
|
||||
"repeating-linear-gradient" => {
|
||||
(Shape::Linear, true, CompatMode::Modern)
|
||||
Some((Shape::Linear, true, CompatMode::Modern))
|
||||
},
|
||||
"-webkit-repeating-linear-gradient" => {
|
||||
(Shape::Linear, true, CompatMode::WebKit)
|
||||
Some((Shape::Linear, true, CompatMode::WebKit))
|
||||
},
|
||||
"radial-gradient" => {
|
||||
(Shape::Radial, false, CompatMode::Modern)
|
||||
Some((Shape::Radial, false, CompatMode::Modern))
|
||||
},
|
||||
"-webkit-radial-gradient" => {
|
||||
(Shape::Radial, false, CompatMode::WebKit)
|
||||
Some((Shape::Radial, false, CompatMode::WebKit))
|
||||
},
|
||||
"repeating-radial-gradient" => {
|
||||
(Shape::Radial, true, CompatMode::Modern)
|
||||
Some((Shape::Radial, true, CompatMode::Modern))
|
||||
},
|
||||
"-webkit-repeating-radial-gradient" => {
|
||||
(Shape::Radial, true, CompatMode::WebKit)
|
||||
Some((Shape::Radial, true, CompatMode::WebKit))
|
||||
},
|
||||
"-webkit-gradient" => {
|
||||
return input.parse_nested_block(|i| Self::parse_webkit_gradient_argument(context, i));
|
||||
},
|
||||
_ => { return Err(()); }
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let (shape, repeating, compat_mode) = match result {
|
||||
Some(result) => result,
|
||||
None => return Err(StyleParseError::UnexpectedFunction(func).into()),
|
||||
};
|
||||
|
||||
let (kind, items) = input.parse_nested_block(|i| {
|
||||
|
@ -191,7 +198,7 @@ impl Parse for Gradient {
|
|||
})?;
|
||||
|
||||
if items.len() < 2 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
Ok(Gradient {
|
||||
|
@ -204,7 +211,8 @@ impl Parse for Gradient {
|
|||
}
|
||||
|
||||
impl Gradient {
|
||||
fn parse_webkit_gradient_argument(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse_webkit_gradient_argument<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
type Point = GenericPosition<Component<X>, Component<Y>>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -259,7 +267,8 @@ impl Gradient {
|
|||
}
|
||||
|
||||
impl Parse for Point {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
input.try(|i| {
|
||||
let x = Component::parse(context, i)?;
|
||||
let y = Component::parse(context, i)?;
|
||||
|
@ -318,7 +327,8 @@ impl Gradient {
|
|||
}
|
||||
|
||||
impl<S: Parse> Parse for Component<S> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(side) = input.try(|i| S::parse(context, i)) {
|
||||
return Ok(Component::Side(side));
|
||||
}
|
||||
|
@ -365,7 +375,7 @@ impl Gradient {
|
|||
|
||||
(kind, reverse_stops)
|
||||
},
|
||||
_ => return Err(()),
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
|
||||
};
|
||||
|
||||
let mut items = input.try(|i| {
|
||||
|
@ -384,11 +394,11 @@ impl Gradient {
|
|||
},
|
||||
"from" => 0.,
|
||||
"to" => 1.,
|
||||
_ => return Err(()),
|
||||
_ => return Err(StyleParseError::UnexpectedFunction(function.clone()).into()),
|
||||
};
|
||||
let color = Color::parse(context, i)?;
|
||||
if color == Color::CurrentColor {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
Ok((color.into(), p))
|
||||
})?;
|
||||
|
@ -450,10 +460,10 @@ impl Gradient {
|
|||
}
|
||||
|
||||
impl GradientKind {
|
||||
fn parse_linear(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ()> {
|
||||
fn parse_linear<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let direction = if let Ok(d) = input.try(|i| LineDirection::parse(context, i, compat_mode)) {
|
||||
input.expect_comma()?;
|
||||
d
|
||||
|
@ -463,10 +473,10 @@ impl GradientKind {
|
|||
Ok(GenericGradientKind::Linear(direction))
|
||||
}
|
||||
|
||||
fn parse_radial(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ()> {
|
||||
fn parse_radial<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let (shape, position) = if compat_mode == CompatMode::Modern {
|
||||
let shape = input.try(|i| EndingShape::parse(context, i, compat_mode));
|
||||
let position = input.try(|i| {
|
||||
|
@ -538,10 +548,10 @@ impl GenericsLineDirection for LineDirection {
|
|||
}
|
||||
|
||||
impl LineDirection {
|
||||
fn parse(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
|
||||
return Ok(LineDirection::Angle(angle));
|
||||
}
|
||||
|
@ -565,10 +575,10 @@ impl LineDirection {
|
|||
}
|
||||
|
||||
impl EndingShape {
|
||||
fn parse(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) {
|
||||
if input.try(|i| i.expect_ident_matching("circle")).is_ok() {
|
||||
return Ok(GenericEndingShape::Circle(Circle::Extent(extent)));
|
||||
|
@ -592,7 +602,7 @@ impl EndingShape {
|
|||
return Ok(GenericEndingShape::Ellipse(Ellipse::Extent(extent)));
|
||||
}
|
||||
if compat_mode == CompatMode::Modern {
|
||||
let pair: Result<_, ()> = input.try(|i| {
|
||||
let pair: Result<_, ParseError> = input.try(|i| {
|
||||
let x = LengthOrPercentage::parse(context, i)?;
|
||||
let y = LengthOrPercentage::parse(context, i)?;
|
||||
Ok((x, y))
|
||||
|
@ -641,18 +651,20 @@ impl EndingShape {
|
|||
}
|
||||
|
||||
impl ShapeExtent {
|
||||
fn parse_with_compat_mode(input: &mut Parser,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ()> {
|
||||
fn parse_with_compat_mode<'i, 't>(input: &mut Parser<'i, 't>,
|
||||
compat_mode: CompatMode)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
match try!(Self::parse(input)) {
|
||||
ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern => Err(()),
|
||||
ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern =>
|
||||
Err(StyleParseError::UnspecifiedError.into()),
|
||||
keyword => Ok(keyword),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GradientItem {
|
||||
fn parse_comma_separated(context: &ParserContext, input: &mut Parser) -> Result<Vec<Self>, ()> {
|
||||
fn parse_comma_separated<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Vec<Self>, ParseError<'i>> {
|
||||
let mut seen_stop = false;
|
||||
let items = try!(input.parse_comma_separated(|input| {
|
||||
if seen_stop {
|
||||
|
@ -665,14 +677,15 @@ impl GradientItem {
|
|||
ColorStop::parse(context, input).map(GenericGradientItem::ColorStop)
|
||||
}));
|
||||
if !seen_stop || items.len() < 2 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for ColorStop {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Ok(ColorStop {
|
||||
color: try!(RGBAColor::parse(context, input)),
|
||||
position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
|
||||
|
@ -681,7 +694,7 @@ impl Parse for ColorStop {
|
|||
}
|
||||
|
||||
impl Parse for PaintWorklet {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.expect_function_matching("paint")?;
|
||||
input.parse_nested_block(|i| {
|
||||
let name = i.expect_ident()?;
|
||||
|
@ -693,7 +706,7 @@ impl Parse for PaintWorklet {
|
|||
}
|
||||
|
||||
impl Parse for ImageRect {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
|
||||
input.parse_nested_block(|i| {
|
||||
let string = i.expect_url_or_string()?;
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
//! [length]: https://drafts.csswg.org/css-values/#lengths
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::{Parser, Token};
|
||||
use cssparser::{Parser, Token, BasicParseError};
|
||||
use euclid::size::Size2D;
|
||||
use font_metrics::FontMetricsQueryResult;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::{cmp, fmt, mem};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::ops::Mul;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
|
||||
use style_traits::values::specified::{AllowedLengthType, AllowedNumericType};
|
||||
use stylesheets::CssRuleType;
|
||||
use super::{AllowQuirks, Number, ToComputedValue};
|
||||
|
@ -451,7 +451,8 @@ impl Mul<CSSFloat> for NoCalcLength {
|
|||
|
||||
impl NoCalcLength {
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
||||
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
|
||||
-> Result<NoCalcLength, ()> {
|
||||
let in_page_rule = context.rule_type.map_or(false, |rule_type| rule_type == CssRuleType::Page);
|
||||
match_ignore_ascii_case! { unit,
|
||||
"px" => Ok(NoCalcLength::Absolute(AbsoluteLength::Px(value))),
|
||||
|
@ -597,47 +598,50 @@ impl Length {
|
|||
}
|
||||
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
|
||||
-> Result<Length, ()> {
|
||||
NoCalcLength::parse_dimension(context, value, unit).map(Length::NoCalc)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_internal(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Length, ()> {
|
||||
match try!(input.next()) {
|
||||
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Length, ParseError<'i>> {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||
Length::parse_dimension(context, value.value, unit),
|
||||
Token::Number(ref value) if num_context.is_ok(value.value) => {
|
||||
if value.value != 0. &&
|
||||
!context.parsing_mode.allows_unitless_lengths() &&
|
||||
!allow_quirks.allowed(context.quirks_mode) {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value.value))))
|
||||
},
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
|
||||
input.parse_nested_block(|input| {
|
||||
return input.parse_nested_block(|input| {
|
||||
CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc)))
|
||||
}),
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
|
||||
/// Parse a non-negative length
|
||||
#[inline]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Length, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Length, ParseError<'i>> {
|
||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
|
||||
/// Parse a non-negative length, allowing quirks.
|
||||
#[inline]
|
||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Length, ()> {
|
||||
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Length, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||
}
|
||||
|
||||
|
@ -657,17 +661,17 @@ impl Length {
|
|||
}
|
||||
|
||||
impl Parse for Length {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl Length {
|
||||
/// Parses a length, with quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +679,8 @@ impl Length {
|
|||
impl<T: Parse> Either<Length, T> {
|
||||
/// Parse a non-negative length
|
||||
#[inline]
|
||||
pub fn parse_non_negative_length(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative_length<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(v) = input.try(|input| T::parse(context, input)) {
|
||||
return Ok(Either::Second(v));
|
||||
}
|
||||
|
@ -710,19 +715,19 @@ impl ToCss for Percentage {
|
|||
|
||||
impl Percentage {
|
||||
/// Parse a specific kind of percentage.
|
||||
pub fn parse_with_clamping_mode(input: &mut Parser,
|
||||
context: AllowedNumericType)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_with_clamping_mode<'i, 't>(input: &mut Parser<'i, 't>,
|
||||
context: AllowedNumericType)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
match try!(input.next()) {
|
||||
Token::Percentage(ref value) if context.is_ok(value.unit_value) => {
|
||||
Ok(Percentage(value.unit_value))
|
||||
}
|
||||
_ => Err(())
|
||||
t => Err(BasicParseError::UnexpectedToken(t).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a percentage token, but rejects it if it's negative.
|
||||
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with_clamping_mode(input, AllowedNumericType::NonNegative)
|
||||
}
|
||||
|
||||
|
@ -741,7 +746,7 @@ impl Percentage {
|
|||
|
||||
impl Parse for Percentage {
|
||||
#[inline]
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with_clamping_mode(input, AllowedNumericType::All)
|
||||
}
|
||||
}
|
||||
|
@ -788,54 +793,58 @@ impl LengthOrPercentage {
|
|||
LengthOrPercentage::Length(NoCalcLength::zero())
|
||||
}
|
||||
|
||||
fn parse_internal(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<LengthOrPercentage, ()>
|
||||
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>>
|
||||
{
|
||||
match try!(input.next()) {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length),
|
||||
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
||||
Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
|
||||
return Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
|
||||
Token::Number(value) if num_context.is_ok(value.value) => {
|
||||
if value.value != 0. &&
|
||||
!context.parsing_mode.allows_unitless_lengths() &&
|
||||
!allow_quirks.allowed(context.quirks_mode) {
|
||||
return Err(())
|
||||
Err(())
|
||||
} else {
|
||||
return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value)))
|
||||
}
|
||||
Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value)))
|
||||
}
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
let calc = try!(input.parse_nested_block(|i| {
|
||||
CalcNode::parse_length_or_percentage(context, i, num_context)
|
||||
}));
|
||||
Ok(LengthOrPercentage::Calc(Box::new(calc)))
|
||||
return Ok(LengthOrPercentage::Calc(Box::new(calc)))
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
|
||||
/// Parse a non-negative length.
|
||||
#[inline]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentage, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
|
||||
/// Parse a non-negative length, with quirks.
|
||||
#[inline]
|
||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<LengthOrPercentage, ()> {
|
||||
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||
}
|
||||
|
||||
/// Parse a length, treating dimensionless numbers as pixels
|
||||
///
|
||||
/// https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value
|
||||
pub fn parse_numbers_are_pixels(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentage, ()> {
|
||||
pub fn parse_numbers_are_pixels<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
if let Ok(lop) = input.try(|i| Self::parse(context, i)) {
|
||||
return Ok(lop)
|
||||
}
|
||||
|
@ -849,9 +858,9 @@ impl LengthOrPercentage {
|
|||
/// Parse a non-negative length, treating dimensionless numbers as pixels
|
||||
///
|
||||
/// This is nonstandard behavior used by Firefox for SVG
|
||||
pub fn parse_numbers_are_pixels_non_negative(context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<LengthOrPercentage, ()> {
|
||||
pub fn parse_numbers_are_pixels_non_negative<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
if let Ok(lop) = input.try(|i| Self::parse_non_negative(context, i)) {
|
||||
return Ok(lop)
|
||||
}
|
||||
|
@ -862,7 +871,7 @@ impl LengthOrPercentage {
|
|||
if num >= 0. {
|
||||
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(num))))
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -877,7 +886,7 @@ impl LengthOrPercentage {
|
|||
|
||||
impl Parse for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
@ -886,9 +895,9 @@ impl LengthOrPercentage {
|
|||
/// Parses a length or a percentage, allowing the unitless length quirk.
|
||||
/// https://quirks.spec.whatwg.org/#the-unitless-length-quirk
|
||||
#[inline]
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
||||
}
|
||||
}
|
||||
|
@ -919,12 +928,13 @@ impl From<Percentage> for LengthOrPercentageOrAuto {
|
|||
}
|
||||
|
||||
impl LengthOrPercentageOrAuto {
|
||||
fn parse_internal(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
match try!(input.next()) {
|
||||
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrAuto::Length),
|
||||
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
||||
|
@ -933,7 +943,7 @@ impl LengthOrPercentageOrAuto {
|
|||
if value.value != 0. &&
|
||||
!context.parsing_mode.allows_unitless_lengths() &&
|
||||
!allow_quirks.allowed(context.quirks_mode) {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(LengthOrPercentageOrAuto::Length(
|
||||
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
|
||||
|
@ -948,21 +958,22 @@ impl LengthOrPercentageOrAuto {
|
|||
Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
|
||||
/// Parse a non-negative length, percentage, or auto.
|
||||
#[inline]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<LengthOrPercentageOrAuto, ParseError<'i>> {
|
||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
|
||||
/// Parse a non-negative length, percentage, or auto.
|
||||
#[inline]
|
||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||
}
|
||||
|
||||
|
@ -984,7 +995,7 @@ impl LengthOrPercentageOrAuto {
|
|||
|
||||
impl Parse for LengthOrPercentageOrAuto {
|
||||
#[inline]
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
@ -992,10 +1003,10 @@ impl Parse for LengthOrPercentageOrAuto {
|
|||
impl LengthOrPercentageOrAuto {
|
||||
/// Parses, with quirks.
|
||||
#[inline]
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
||||
}
|
||||
}
|
||||
|
@ -1012,13 +1023,14 @@ pub enum LengthOrPercentageOrNone {
|
|||
}
|
||||
|
||||
impl LengthOrPercentageOrNone {
|
||||
fn parse_internal(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<LengthOrPercentageOrNone, ()>
|
||||
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
num_context: AllowedLengthType,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<LengthOrPercentageOrNone, ParseError<'i>>
|
||||
{
|
||||
match try!(input.next()) {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrNone::Length),
|
||||
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
||||
|
@ -1026,7 +1038,7 @@ impl LengthOrPercentageOrNone {
|
|||
Token::Number(value) if num_context.is_ok(value.value) => {
|
||||
if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() &&
|
||||
!allow_quirks.allowed(context.quirks_mode) {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(LengthOrPercentageOrNone::Length(
|
||||
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
|
||||
|
@ -1041,28 +1053,29 @@ impl LengthOrPercentageOrNone {
|
|||
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
||||
Ok(LengthOrPercentageOrNone::None),
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
|
||||
/// Parse a non-negative LengthOrPercentageOrNone.
|
||||
#[inline]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
|
||||
/// Parse a non-negative LengthOrPercentageOrNone, with quirks.
|
||||
#[inline]
|
||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for LengthOrPercentageOrNone {
|
||||
#[inline]
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_internal(context, input, AllowedLengthType::All, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
@ -1095,9 +1108,11 @@ pub enum LengthOrPercentageOrAutoOrContent {
|
|||
|
||||
impl LengthOrPercentageOrAutoOrContent {
|
||||
/// Parse a non-negative LengthOrPercentageOrAutoOrContent.
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let num_context = AllowedLengthType::NonNegative;
|
||||
match try!(input.next()) {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||
NoCalcLength::parse_dimension(context, value.value, unit)
|
||||
.map(LengthOrPercentageOrAutoOrContent::Length),
|
||||
|
@ -1116,7 +1131,7 @@ impl LengthOrPercentageOrAutoOrContent {
|
|||
Ok(LengthOrPercentageOrAutoOrContent::Calc(Box::new(calc)))
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
|
||||
/// Returns the `auto` value.
|
||||
|
@ -1140,7 +1155,8 @@ pub type LengthOrNumber = Either<Length, Number>;
|
|||
|
||||
impl LengthOrNumber {
|
||||
/// Parse a non-negative LengthOrNumber.
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
// We try to parse as a Number first because, for cases like
|
||||
// LengthOrNumber, we want "0" to be parsed as a plain Number rather
|
||||
// than a Length (0px); this matches the behaviour of all major browsers
|
||||
|
@ -1170,18 +1186,18 @@ pub enum MozLength {
|
|||
}
|
||||
|
||||
impl Parse for MozLength {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
MozLength::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl MozLength {
|
||||
/// Parses, with quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||
input.try(ExtremumLength::parse).map(MozLength::ExtremumLength)
|
||||
.or_else(|()| input.try(|i| LengthOrPercentageOrAuto::parse_non_negative_quirky(context, i, allow_quirks))
|
||||
.or_else(|_| input.try(|i| LengthOrPercentageOrAuto::parse_non_negative_quirky(context, i, allow_quirks))
|
||||
.map(MozLength::LengthOrPercentageOrAuto))
|
||||
}
|
||||
}
|
||||
|
@ -1196,18 +1212,18 @@ pub enum MaxLength {
|
|||
}
|
||||
|
||||
impl Parse for MaxLength {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
MaxLength::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl MaxLength {
|
||||
/// Parses, with quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||
input.try(ExtremumLength::parse).map(MaxLength::ExtremumLength)
|
||||
.or_else(|()| input.try(|i| LengthOrPercentageOrNone::parse_non_negative_quirky(context, i, allow_quirks))
|
||||
.or_else(|_| input.try(|i| LengthOrPercentageOrNone::parse_non_negative_quirky(context, i, allow_quirks))
|
||||
.map(MaxLength::LengthOrPercentageOrNone))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
use Namespace;
|
||||
use context::QuirksMode;
|
||||
use cssparser::{Parser, Token, serialize_identifier};
|
||||
use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
|
||||
use parser::{ParserContext, Parse};
|
||||
use self::grid::TrackSizeOrRepeat;
|
||||
use self::url::SpecifiedUrl;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::f32;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
||||
use super::computed::{self, Context};
|
||||
|
@ -68,6 +68,7 @@ pub mod transform;
|
|||
pub mod url {
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use style_traits::ParseError;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
|
@ -76,7 +77,7 @@ pub use ::servo::url::*;
|
|||
pub use ::gecko::url::*;
|
||||
|
||||
impl Parse for SpecifiedUrl {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let url = try!(input.expect_url());
|
||||
Self::parse_from_string(url, context)
|
||||
}
|
||||
|
@ -91,9 +92,10 @@ no_viewport_percentage!(SpecifiedUrl);
|
|||
}
|
||||
|
||||
/// Parse an `<integer>` value, handling `calc()` correctly.
|
||||
pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
||||
pub fn parse_integer<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Integer, ParseError<'i>> {
|
||||
match try!(input.next()) {
|
||||
Token::Number(ref value) => value.int_value.ok_or(()).map(Integer::new),
|
||||
Token::Number(ref value) => value.int_value.ok_or(StyleParseError::UnspecifiedError.into()).map(Integer::new),
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
let result = try!(input.parse_nested_block(|i| {
|
||||
CalcNode::parse_integer(context, i)
|
||||
|
@ -101,21 +103,22 @@ pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Inte
|
|||
|
||||
Ok(Integer::from_calc(result))
|
||||
}
|
||||
_ => Err(())
|
||||
t => Err(BasicParseError::UnexpectedToken(t).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a `<number>` value, handling `calc()` correctly, and without length
|
||||
/// limitations.
|
||||
pub fn parse_number(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
|
||||
pub fn parse_number<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Number, ParseError<'i>> {
|
||||
parse_number_with_clamping_mode(context, input, AllowedNumericType::All)
|
||||
}
|
||||
|
||||
/// Parse a `<number>` value, with a given clamping mode.
|
||||
pub fn parse_number_with_clamping_mode(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
clamping_mode: AllowedNumericType)
|
||||
-> Result<Number, ()> {
|
||||
pub fn parse_number_with_clamping_mode<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
clamping_mode: AllowedNumericType)
|
||||
-> Result<Number, ParseError<'i>> {
|
||||
match try!(input.next()) {
|
||||
Token::Number(ref value) if clamping_mode.is_ok(value.value) => {
|
||||
Ok(Number {
|
||||
|
@ -133,7 +136,7 @@ pub fn parse_number_with_clamping_mode(context: &ParserContext,
|
|||
calc_clamping_mode: Some(clamping_mode),
|
||||
})
|
||||
}
|
||||
_ => Err(())
|
||||
t => Err(BasicParseError::UnexpectedToken(t).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,18 +223,19 @@ impl Angle {
|
|||
|
||||
impl Parse for Angle {
|
||||
/// Parses an angle according to CSS-VALUES § 6.1.
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match try!(input.next()) {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) => {
|
||||
Angle::parse_dimension(value.value,
|
||||
unit,
|
||||
/* from_calc = */ false)
|
||||
}
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
||||
return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
||||
}
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,8 +264,10 @@ impl Angle {
|
|||
///
|
||||
/// We can remove this and get back to the unified version Angle::parse once
|
||||
/// https://github.com/w3c/csswg-drafts/issues/1162 is resolved.
|
||||
pub fn parse_with_unitless(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match try!(input.next()) {
|
||||
pub fn parse_with_unitless<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
let token = try!(input.next());
|
||||
match token {
|
||||
Token::Dimension(ref value, ref unit) => {
|
||||
Angle::parse_dimension(value.value,
|
||||
unit,
|
||||
|
@ -269,10 +275,10 @@ impl Angle {
|
|||
}
|
||||
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
||||
return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
||||
}
|
||||
_ => Err(())
|
||||
}
|
||||
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +343,7 @@ impl Time {
|
|||
let seconds = match_ignore_ascii_case! { unit,
|
||||
"s" => value,
|
||||
"ms" => value / 1000.0,
|
||||
_ => return Err(()),
|
||||
_ => return Err(())
|
||||
};
|
||||
|
||||
Ok(Time {
|
||||
|
@ -354,25 +360,29 @@ impl Time {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_with_clamping_mode(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
clamping_mode: AllowedNumericType) -> Result<Self, ()> {
|
||||
fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
clamping_mode: AllowedNumericType)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
match input.next() {
|
||||
Ok(Token::Dimension(ref value, ref unit)) if clamping_mode.is_ok(value.value) => {
|
||||
Time::parse_dimension(value.value, &unit, /* from_calc = */ false)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {
|
||||
match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) {
|
||||
Ok(time) if clamping_mode.is_ok(time.seconds) => Ok(time),
|
||||
_ => Err(()),
|
||||
_ => Err(StyleParseError::UnspecifiedError.into()),
|
||||
}
|
||||
}
|
||||
_ => Err(())
|
||||
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
Err(e) => Err(e.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse <time> that values are non-negative.
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
|
||||
}
|
||||
}
|
||||
|
@ -393,7 +403,7 @@ impl ToComputedValue for Time {
|
|||
}
|
||||
|
||||
impl Parse for Time {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +435,7 @@ pub struct Number {
|
|||
no_viewport_percentage!(Number);
|
||||
|
||||
impl Parse for Number {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
parse_number(context, input)
|
||||
}
|
||||
}
|
||||
|
@ -445,7 +455,8 @@ impl Number {
|
|||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Number, ParseError<'i>> {
|
||||
if context.parsing_mode.allows_all_numeric_values() {
|
||||
parse_number(context, input)
|
||||
} else {
|
||||
|
@ -454,7 +465,8 @@ impl Number {
|
|||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_at_least_one(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
|
||||
pub fn parse_at_least_one<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Number, ParseError<'i>> {
|
||||
if context.parsing_mode.allows_all_numeric_values() {
|
||||
parse_number(context, input)
|
||||
} else {
|
||||
|
@ -506,10 +518,10 @@ pub enum NumberOrPercentage {
|
|||
no_viewport_percentage!(NumberOrPercentage);
|
||||
|
||||
impl NumberOrPercentage {
|
||||
fn parse_with_clamping_mode(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
type_: AllowedNumericType)
|
||||
-> Result<Self, ()> {
|
||||
fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
type_: AllowedNumericType)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(i, type_)) {
|
||||
return Ok(NumberOrPercentage::Percentage(per));
|
||||
}
|
||||
|
@ -518,13 +530,14 @@ impl NumberOrPercentage {
|
|||
}
|
||||
|
||||
/// Parse a non-negative number or percentage.
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for NumberOrPercentage {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
|
||||
}
|
||||
}
|
||||
|
@ -537,7 +550,7 @@ pub struct Opacity(Number);
|
|||
no_viewport_percentage!(Opacity);
|
||||
|
||||
impl Parse for Opacity {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
parse_number(context, input).map(Opacity)
|
||||
}
|
||||
}
|
||||
|
@ -590,27 +603,31 @@ impl Integer {
|
|||
no_viewport_percentage!(Integer);
|
||||
|
||||
impl Parse for Integer {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
parse_integer(context, input)
|
||||
}
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_with_minimum(context: &ParserContext, input: &mut Parser, min: i32) -> Result<Integer, ()> {
|
||||
pub fn parse_with_minimum<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, min: i32)
|
||||
-> Result<Integer, ParseError<'i>> {
|
||||
match parse_integer(context, input) {
|
||||
Ok(value) if value.value() >= min => Ok(value),
|
||||
_ => Err(()),
|
||||
Ok(_value) => Err(StyleParseError::UnspecifiedError.into()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Integer, ParseError<'i>> {
|
||||
Integer::parse_with_minimum(context, input, 0)
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_positive(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
||||
pub fn parse_positive<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Integer, ParseError<'i>> {
|
||||
Integer::parse_with_minimum(context, input, 1)
|
||||
}
|
||||
}
|
||||
|
@ -647,11 +664,11 @@ pub type IntegerOrAuto = Either<Integer, Auto>;
|
|||
|
||||
impl IntegerOrAuto {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_positive(context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<IntegerOrAuto, ()> {
|
||||
pub fn parse_positive<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<IntegerOrAuto, ParseError<'i>> {
|
||||
match IntegerOrAuto::parse(context, input) {
|
||||
Ok(Either::First(integer)) if integer.value() <= 0 => Err(()),
|
||||
Ok(Either::First(integer)) if integer.value() <= 0 => Err(StyleParseError::UnspecifiedError.into()),
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +756,10 @@ impl ToCss for Shadow {
|
|||
impl Shadow {
|
||||
// disable_spread_and_inset is for filter: drop-shadow(...)
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser, disable_spread_and_inset: bool) -> Result<Shadow, ()> {
|
||||
pub fn parse<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
disable_spread_and_inset: bool)
|
||||
-> Result<Shadow, ParseError<'i>> {
|
||||
let mut lengths = [Length::zero(), Length::zero(), Length::zero(), Length::zero()];
|
||||
let mut lengths_parsed = false;
|
||||
let mut color = None;
|
||||
|
@ -779,7 +799,7 @@ impl Shadow {
|
|||
|
||||
// Lengths must be specified.
|
||||
if !lengths_parsed {
|
||||
return Err(())
|
||||
return Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
debug_assert!(!disable_spread_and_inset || lengths[3] == Length::zero());
|
||||
|
@ -841,7 +861,8 @@ pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
|
|||
|
||||
impl LengthOrPercentageOrNumber {
|
||||
/// parse a <length-percentage> | <number> enforcing that the contents aren't negative
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
// NB: Parse numbers before Lengths so we are consistent about how to
|
||||
// recognize and serialize "0".
|
||||
if let Ok(num) = input.try(|i| Number::parse_non_negative(context, i)) {
|
||||
|
@ -928,19 +949,19 @@ impl ToComputedValue for ClipRect {
|
|||
}
|
||||
|
||||
impl Parse for ClipRect {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl ClipRect {
|
||||
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
|
||||
pub fn parse_quirky(context: &ParserContext, input: &mut Parser,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||
use values::specified::Length;
|
||||
|
||||
fn parse_argument(context: &ParserContext, input: &mut Parser,
|
||||
allow_quirks: AllowQuirks) -> Result<Option<Length>, ()> {
|
||||
fn parse_argument<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks) -> Result<Option<Length>, ParseError<'i>> {
|
||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||
Ok(None)
|
||||
} else {
|
||||
|
@ -948,8 +969,9 @@ impl ClipRect {
|
|||
}
|
||||
}
|
||||
|
||||
if !try!(input.expect_function()).eq_ignore_ascii_case("rect") {
|
||||
return Err(())
|
||||
let func = try!(input.expect_function());
|
||||
if !func.eq_ignore_ascii_case("rect") {
|
||||
return Err(StyleParseError::UnexpectedFunction(func).into())
|
||||
}
|
||||
|
||||
input.parse_nested_block(|input| {
|
||||
|
@ -984,8 +1006,8 @@ pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
|||
|
||||
impl ClipRectOrAuto {
|
||||
/// Parses a ClipRect or Auto, allowing quirks.
|
||||
pub fn parse_quirky(context: &ParserContext, input: &mut Parser,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
|
||||
Ok(Either::First(v))
|
||||
} else {
|
||||
|
@ -1035,7 +1057,7 @@ pub struct Attr {
|
|||
}
|
||||
|
||||
impl Parse for Attr {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Attr, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Attr, ParseError<'i>> {
|
||||
input.expect_function_matching("attr")?;
|
||||
input.parse_nested_block(|i| Attr::parse_function(context, i))
|
||||
}
|
||||
|
@ -1068,25 +1090,28 @@ fn get_id_for_namespace(_: &Namespace, _: &ParserContext) -> Result<NamespaceId,
|
|||
impl Attr {
|
||||
/// Parse contents of attr() assuming we have already parsed `attr` and are
|
||||
/// within a parse_nested_block()
|
||||
pub fn parse_function(context: &ParserContext, input: &mut Parser) -> Result<Attr, ()> {
|
||||
pub fn parse_function<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Attr, ParseError<'i>> {
|
||||
// Syntax is `[namespace? `|`]? ident`
|
||||
// no spaces allowed
|
||||
let first = input.try(|i| i.expect_ident()).ok();
|
||||
if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
|
||||
match token {
|
||||
Token::Delim('|') => {}
|
||||
_ => return Err(()),
|
||||
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
}
|
||||
// must be followed by an ident
|
||||
let second_token = match input.next_including_whitespace()? {
|
||||
Token::Ident(second) => second,
|
||||
_ => return Err(()),
|
||||
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||
};
|
||||
|
||||
let ns_with_id = if let Some(ns) = first {
|
||||
let ns: Namespace = ns.into();
|
||||
let id = get_id_for_namespace(&ns, context)?;
|
||||
Some((ns, id))
|
||||
let id: Result<_, ParseError> =
|
||||
get_id_for_namespace(&ns, context)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into());
|
||||
Some((ns, id?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -1102,7 +1127,7 @@ impl Attr {
|
|||
attribute: first.into_owned(),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
Err(StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::{HasViewportPercentage, ToCss};
|
||||
use style_traits::{HasViewportPercentage, ToCss, ParseError};
|
||||
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage};
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::generics::position::Position as GenericPosition;
|
||||
|
@ -50,17 +50,17 @@ define_css_keyword_enum! { Y:
|
|||
add_impls_for_keyword_enum!(Y);
|
||||
|
||||
impl Parse for Position {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl Position {
|
||||
/// Parses a `<position>`, with quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
match input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
|
||||
Ok(x_pos @ PositionComponent::Center) => {
|
||||
if let Ok(y_pos) = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
|
||||
|
@ -104,7 +104,7 @@ impl Position {
|
|||
Err(_) => {},
|
||||
}
|
||||
let y_keyword = Y::parse(input)?;
|
||||
let lop_and_x_pos: Result<_, ()> = input.try(|i| {
|
||||
let lop_and_x_pos: Result<_, ParseError> = input.try(|i| {
|
||||
let y_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
|
||||
if let Ok(x_keyword) = i.try(X::parse) {
|
||||
let x_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
|
||||
|
@ -167,17 +167,17 @@ impl<S> HasViewportPercentage for PositionComponent<S> {
|
|||
}
|
||||
|
||||
impl<S: Parse> Parse for PositionComponent<S> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Parse> PositionComponent<S> {
|
||||
/// Parses a component of a CSS position, with quirks.
|
||||
pub fn parse_quirky(context: &ParserContext,
|
||||
input: &mut Parser,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ()> {
|
||||
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
|
||||
return Ok(PositionComponent::Center);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use cssparser::Parser;
|
||||
use parser::ParserContext;
|
||||
use style_traits::ParseError;
|
||||
use values::generics::rect::Rect;
|
||||
use values::specified::length::LengthOrNumber;
|
||||
|
||||
|
@ -15,7 +16,8 @@ pub type LengthOrNumberRect = Rect<LengthOrNumber>;
|
|||
impl LengthOrNumberRect {
|
||||
/// Parses a `LengthOrNumberRect`, rejecting negative values.
|
||||
#[inline]
|
||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<Self, ParseError<'i>> {
|
||||
Rect::parse_with(context, input, LengthOrNumber::parse_non_negative)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use std::ascii::AsciiExt;
|
||||
use style_traits::ParseError;
|
||||
use values::computed::{Context, ToComputedValue};
|
||||
use values::computed::text::LineHeight as ComputedLineHeight;
|
||||
use values::generics::text::InitialLetter as GenericInitialLetter;
|
||||
|
@ -28,7 +30,7 @@ pub type WordSpacing = Spacing<LengthOrPercentage>;
|
|||
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
|
||||
|
||||
impl Parse for InitialLetter {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(GenericInitialLetter::Normal);
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ impl Parse for InitialLetter {
|
|||
}
|
||||
|
||||
impl Parse for LetterSpacing {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Spacing::parse_with(context, input, |c, i| {
|
||||
Length::parse_quirky(c, i, AllowQuirks::Yes)
|
||||
})
|
||||
|
@ -47,7 +49,7 @@ impl Parse for LetterSpacing {
|
|||
}
|
||||
|
||||
impl Parse for WordSpacing {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
Spacing::parse_with(context, input, |c, i| {
|
||||
LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
|
||||
})
|
||||
|
@ -55,22 +57,23 @@ impl Parse for WordSpacing {
|
|||
}
|
||||
|
||||
impl Parse for LineHeight {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
|
||||
return Ok(GenericLineHeight::Number(number))
|
||||
}
|
||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||
return Ok(GenericLineHeight::Length(lop))
|
||||
}
|
||||
match &input.expect_ident()? {
|
||||
ident if ident.eq_ignore_ascii_case("normal") => {
|
||||
let ident = input.expect_ident()?;
|
||||
match ident {
|
||||
ref ident if ident.eq_ignore_ascii_case("normal") => {
|
||||
Ok(GenericLineHeight::Normal)
|
||||
},
|
||||
#[cfg(feature = "gecko")]
|
||||
ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
|
||||
ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
|
||||
Ok(GenericLineHeight::MozBlockHeight)
|
||||
},
|
||||
_ => Err(()),
|
||||
ident => Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
use cssparser::Parser;
|
||||
use euclid::Point2D;
|
||||
use parser::{Parse, ParserContext};
|
||||
use selectors::parser::SelectorParseError;
|
||||
use style_traits::{ParseError, StyleParseError};
|
||||
use values::computed::{LengthOrPercentage as ComputedLengthOrPercentage, Context, ToComputedValue};
|
||||
use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
||||
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction};
|
||||
|
@ -34,7 +36,7 @@ pub enum OriginComponent<S> {
|
|||
pub type TimingFunction = GenericTimingFunction<Integer, Number>;
|
||||
|
||||
impl Parse for TransformOrigin {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
let parse_depth = |input: &mut Parser| {
|
||||
input.try(|i| Length::parse(context, i)).unwrap_or(Length::from_px(0.))
|
||||
};
|
||||
|
@ -85,7 +87,7 @@ impl Parse for TransformOrigin {
|
|||
impl<S> Parse for OriginComponent<S>
|
||||
where S: Parse,
|
||||
{
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
|
||||
return Ok(OriginComponent::Center);
|
||||
}
|
||||
|
@ -123,7 +125,7 @@ impl<S> ToComputedValue for OriginComponent<S>
|
|||
}
|
||||
|
||||
impl Parse for TimingFunction {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(keyword) = input.try(TimingKeyword::parse) {
|
||||
return Ok(GenericTimingFunction::Keyword(keyword));
|
||||
}
|
||||
|
@ -131,13 +133,13 @@ impl Parse for TimingFunction {
|
|||
let position = match_ignore_ascii_case! { &ident,
|
||||
"step-start" => StepPosition::Start,
|
||||
"step-end" => StepPosition::End,
|
||||
_ => return Err(()),
|
||||
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
|
||||
};
|
||||
return Ok(GenericTimingFunction::Steps(Integer::new(1), position));
|
||||
}
|
||||
let function = input.expect_function()?;
|
||||
input.parse_nested_block(|i| {
|
||||
match_ignore_ascii_case! { &function,
|
||||
input.parse_nested_block(move |i| {
|
||||
(match_ignore_ascii_case! { &function,
|
||||
"cubic-bezier" => {
|
||||
let p1x = Number::parse(context, i)?;
|
||||
i.expect_comma()?;
|
||||
|
@ -148,7 +150,7 @@ impl Parse for TimingFunction {
|
|||
let p2y = Number::parse(context, i)?;
|
||||
|
||||
if p1x.get() < 0.0 || p1x.get() > 1.0 || p2x.get() < 0.0 || p2x.get() > 1.0 {
|
||||
return Err(());
|
||||
return Err(StyleParseError::UnspecifiedError.into());
|
||||
}
|
||||
|
||||
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
|
||||
|
@ -167,7 +169,7 @@ impl Parse for TimingFunction {
|
|||
Ok(GenericTimingFunction::Frames(frames))
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,10 @@ gecko = []
|
|||
|
||||
[dependencies]
|
||||
app_units = "0.4.1"
|
||||
cssparser = "0.13.7"
|
||||
cssparser = "0.14.0"
|
||||
euclid = "0.13"
|
||||
heapsize = {version = "0.4", optional = true}
|
||||
heapsize_derive = {version = "0.1", optional = true}
|
||||
selectors = { path = "../selectors" }
|
||||
serde = {version = "0.9", optional = true}
|
||||
serde_derive = {version = "0.9", optional = true}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче