From 3e5f69118b90cd03ecfe1663b1568e5843e28b63 Mon Sep 17 00:00:00 2001 From: Connor Skees Date: Sun, 2 Aug 2020 23:00:00 -0400 Subject: [PATCH] disallow more at-rules in `@function` --- src/parse/function.rs | 4 ++ src/parse/import.rs | 4 ++ src/parse/keyframes.rs | 4 ++ src/parse/mixin.rs | 4 ++ src/parse/mod.rs | 31 ++++++++++++ tests/functions.rs | 110 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+) diff --git a/src/parse/function.rs b/src/parse/function.rs index fb8b516..4560abe 100644 --- a/src/parse/function.rs +++ b/src/parse/function.rs @@ -31,6 +31,10 @@ impl<'a> Parser<'a> { return Err(("Functions may not be declared in control directives.", span).into()); } + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + if RESERVED_IDENTIFIERS.contains(&unvendor(&name)) { return Err(("Invalid function name.", span).into()); } diff --git a/src/parse/import.rs b/src/parse/import.rs index dbcfcb6..ce6d918 100644 --- a/src/parse/import.rs +++ b/src/parse/import.rs @@ -111,6 +111,10 @@ impl<'a> Parser<'a> { } pub(super) fn import(&mut self) -> SassResult> { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + self.whitespace(); match self.toks.peek() { diff --git a/src/parse/keyframes.rs b/src/parse/keyframes.rs index 0e6e1fe..c02092f 100644 --- a/src/parse/keyframes.rs +++ b/src/parse/keyframes.rs @@ -185,6 +185,10 @@ impl<'a> Parser<'a> { } pub(super) fn parse_keyframes(&mut self, rule: String) -> SassResult { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + let name = self.parse_keyframes_name()?; self.whitespace(); diff --git a/src/parse/mixin.rs b/src/parse/mixin.rs index db4a5a1..7b55003 100644 --- a/src/parse/mixin.rs +++ b/src/parse/mixin.rs @@ -66,6 +66,10 @@ impl<'a> Parser<'a> { } pub(super) fn parse_include(&mut self) -> SassResult> { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + self.whitespace_or_comment(); let name = self.parse_identifier()?.map_node(Into::into); diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 06f4dc3..0fd3eb5 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -131,6 +131,14 @@ impl<'a> Parser<'a> { } } AtRuleKind::AtRoot => { + if self.flags.in_function() { + return Err(( + "This at-rule is not allowed here.", + kind_string.span, + ) + .into()); + } + if self.at_root { stmts.append(&mut self.parse_at_root()?); } else { @@ -186,6 +194,14 @@ impl<'a> Parser<'a> { AtRuleKind::For => stmts.append(&mut self.parse_for()?), AtRuleKind::While => stmts.append(&mut self.parse_while()?), AtRuleKind::Charset => { + if self.flags.in_function() { + return Err(( + "This at-rule is not allowed here.", + kind_string.span, + ) + .into()); + } + read_until_semicolon_or_closing_curly_brace(self.toks)?; if let Some(Token { kind: ';', .. }) = self.toks.peek() { self.toks.next(); @@ -532,6 +548,10 @@ impl<'a> Parser<'a> { impl<'a> Parser<'a> { fn parse_unknown_at_rule(&mut self, name: String) -> SassResult { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + let mut params = String::new(); self.whitespace(); if let Some(Token { kind: ';', .. }) | None = self.toks.peek() { @@ -595,6 +615,10 @@ impl<'a> Parser<'a> { } fn parse_media(&mut self) -> SassResult { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + let query = self.parse_media_query_list()?; self.whitespace(); @@ -690,6 +714,9 @@ impl<'a> Parser<'a> { } fn parse_extend(&mut self) -> SassResult<()> { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } // todo: track when inside ruleset or `@content` // if !self.in_style_rule && !self.in_mixin && !self.in_content_block { // return Err(("@extend may only be used within style rules.", self.span_before).into()); @@ -757,6 +784,10 @@ impl<'a> Parser<'a> { } fn parse_supports(&mut self) -> SassResult { + if self.flags.in_function() { + return Err(("This at-rule is not allowed here.", self.span_before).into()); + } + let params = self.parse_media_args()?; if params.is_empty() { diff --git a/tests/functions.rs b/tests/functions.rs index 4b569a0..007dc25 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -195,3 +195,113 @@ test!( }", "a {\n color: foo;\n color: bar;\n}\n" ); +error!( + disallows_unknown_at_rule, + "@function foo() { + @foo; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_media_query, + "@function foo() { + @media screen {}; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_at_root, + "@function foo() { + @at-root {}; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_charset, + "@function foo() { + @charset 'utf-8'; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_extend, + "@function foo() { + @extend a; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_keyframes, + "@function foo() { + @keyframes foo {} + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_supports, + "@function foo() { + @supports foo {} + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_import, + "@function foo() { + @import \"foo.css\"; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_inner_function_declaration, + "@function foo() { + @function bar() {} + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +); +error!( + disallows_include, + "@function foo() { + @include bar; + } + + a { + color: foo(); + }", + "Error: This at-rule is not allowed here." +);