resolve regression in @mixin
scoping
This commit is contained in:
parent
1f4698378d
commit
09a322f175
@ -1,6 +1,7 @@
|
||||
# 0.9.1
|
||||
|
||||
- fix regression in which `@at-root` would panic when placed after a ruleset
|
||||
- fix regression related to `@mixin` scoping and outer, local variables
|
||||
- fix regression related to `@mixin` and `@function` scoping when combined with outer, local variables
|
||||
|
||||
# 0.9.0
|
||||
|
||||
|
@ -25,6 +25,14 @@ impl<T> NeverEmptyVec<T> {
|
||||
self.rest.last_mut().unwrap_or(&mut self.first)
|
||||
}
|
||||
|
||||
pub fn first(&mut self) -> &T {
|
||||
&self.first
|
||||
}
|
||||
|
||||
pub fn first_mut(&mut self) -> &mut T {
|
||||
&mut self.first
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: T) {
|
||||
self.rest.push(value)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ use std::mem;
|
||||
use codemap::Spanned;
|
||||
use peekmore::PeekMore;
|
||||
|
||||
use super::{Parser, Stmt};
|
||||
use crate::{
|
||||
args::CallArgs,
|
||||
atrule::Function,
|
||||
@ -13,6 +12,8 @@ use crate::{
|
||||
Token,
|
||||
};
|
||||
|
||||
use super::{NeverEmptyVec, Parser, Stmt};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub(super) fn parse_function(&mut self) -> SassResult<()> {
|
||||
if self.in_mixin {
|
||||
@ -62,13 +63,12 @@ impl<'a> Parser<'a> {
|
||||
|
||||
pub fn eval_function(&mut self, mut function: Function, args: CallArgs) -> SassResult<Value> {
|
||||
self.eval_fn_args(&mut function, args)?;
|
||||
self.scopes.push(function.scope);
|
||||
|
||||
let mut return_value = Parser {
|
||||
toks: &mut function.body.into_iter().peekmore(),
|
||||
map: self.map,
|
||||
path: self.path,
|
||||
scopes: self.scopes,
|
||||
scopes: &mut NeverEmptyVec::new(function.scope),
|
||||
global_scope: self.global_scope,
|
||||
super_selectors: self.super_selectors,
|
||||
span_before: self.span_before,
|
||||
@ -81,8 +81,6 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
.parse()?;
|
||||
|
||||
self.scopes.pop();
|
||||
|
||||
debug_assert!(return_value.len() <= 1);
|
||||
match return_value
|
||||
.pop()
|
||||
|
@ -6,13 +6,12 @@ use crate::{
|
||||
args::{CallArgs, FuncArgs},
|
||||
atrule::Mixin,
|
||||
error::SassResult,
|
||||
scope::Scope,
|
||||
utils::read_until_closing_curly_brace,
|
||||
value::Value,
|
||||
Token,
|
||||
};
|
||||
|
||||
use super::{Parser, Stmt};
|
||||
use super::{NeverEmptyVec, Parser, Stmt};
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub(super) fn parse_mixin(&mut self) -> SassResult<()> {
|
||||
@ -41,7 +40,7 @@ impl<'a> Parser<'a> {
|
||||
// this is blocked on figuring out just how to check for this. presumably we could have a check
|
||||
// not when parsing initially, but rather when `@include`ing to see if an `@content` was found.
|
||||
|
||||
let mixin = Mixin::new(Scope::new(), args, body, false);
|
||||
let mixin = Mixin::new(self.scopes.last().clone(), args, body, false);
|
||||
|
||||
if self.at_root {
|
||||
self.global_scope.insert_mixin(name, mixin);
|
||||
@ -97,13 +96,11 @@ impl<'a> Parser<'a> {
|
||||
let mut mixin = self.scopes.last().get_mixin(name, self.global_scope)?;
|
||||
self.eval_mixin_args(&mut mixin, args)?;
|
||||
|
||||
self.scopes.push(mixin.scope);
|
||||
|
||||
let body = Parser {
|
||||
toks: &mut mixin.body,
|
||||
map: self.map,
|
||||
path: self.path,
|
||||
scopes: self.scopes,
|
||||
scopes: &mut NeverEmptyVec::new(mixin.scope),
|
||||
global_scope: self.global_scope,
|
||||
super_selectors: self.super_selectors,
|
||||
span_before: self.span_before,
|
||||
@ -116,8 +113,6 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
.parse()?;
|
||||
|
||||
self.scopes.pop();
|
||||
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,11 @@ impl<'a> Parser<'a> {
|
||||
scope.insert_var(ident.clone(), value.value.clone())?;
|
||||
}
|
||||
}
|
||||
if self.scopes.first().var_exists_no_global(&ident) {
|
||||
self.scopes
|
||||
.first_mut()
|
||||
.insert_var(ident.clone(), value.value.clone())?;
|
||||
}
|
||||
self.scopes.last_mut().insert_var(ident, value.value)?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -99,3 +99,25 @@ error!(
|
||||
body_missing_closing_curly_brace,
|
||||
"@function foo() {", "Error: expected \"}\"."
|
||||
);
|
||||
test!(
|
||||
does_not_modify_local_variables,
|
||||
"@function bar($color-name) {
|
||||
@if $color-name==bar {
|
||||
@error bar;
|
||||
}
|
||||
|
||||
$color: bar;
|
||||
@return null;
|
||||
}
|
||||
|
||||
@function foo($a, $b) {
|
||||
@return \"success!\";
|
||||
}
|
||||
|
||||
a {
|
||||
$color: foo;
|
||||
|
||||
color: foo(bar($color), bar($color));
|
||||
}",
|
||||
"a {\n color: \"success!\";\n}\n"
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user