avoid cloning the entire scope
This commit is contained in:
parent
316316d3a0
commit
02efd09d80
@ -1,4 +1,4 @@
|
|||||||
use crate::{args::FuncArgs, scope::Scopes, Token};
|
use crate::{args::FuncArgs, Token};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Mixin {
|
pub(crate) struct Mixin {
|
||||||
@ -28,7 +28,6 @@ impl Mixin {
|
|||||||
pub(crate) struct Content {
|
pub(crate) struct Content {
|
||||||
pub content: Option<Vec<Token>>,
|
pub content: Option<Vec<Token>>,
|
||||||
pub content_args: Option<FuncArgs>,
|
pub content_args: Option<FuncArgs>,
|
||||||
pub scopes: Scopes,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Content {
|
impl Content {
|
||||||
@ -36,7 +35,6 @@ impl Content {
|
|||||||
Self {
|
Self {
|
||||||
content: None,
|
content: None,
|
||||||
content_args: None,
|
content_args: None,
|
||||||
scopes: Scopes::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,7 @@ pub fn from_path(p: &str) -> Result<String> {
|
|||||||
at_root: true,
|
at_root: true,
|
||||||
at_root_has_selector: false,
|
at_root_has_selector: false,
|
||||||
extender: &mut Extender::new(empty_span),
|
extender: &mut Extender::new(empty_span),
|
||||||
|
content_scopes: &mut Scopes::new(),
|
||||||
}
|
}
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| raw_to_parse_error(&map, *e))?;
|
.map_err(|e| raw_to_parse_error(&map, *e))?;
|
||||||
@ -199,6 +200,7 @@ pub fn from_string(p: String) -> Result<String> {
|
|||||||
at_root: true,
|
at_root: true,
|
||||||
at_root_has_selector: false,
|
at_root_has_selector: false,
|
||||||
extender: &mut Extender::new(empty_span),
|
extender: &mut Extender::new(empty_span),
|
||||||
|
content_scopes: &mut Scopes::new(),
|
||||||
}
|
}
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| raw_to_parse_error(&map, *e))?;
|
.map_err(|e| raw_to_parse_error(&map, *e))?;
|
||||||
@ -232,6 +234,7 @@ pub fn from_string(p: String) -> std::result::Result<String, JsValue> {
|
|||||||
at_root: true,
|
at_root: true,
|
||||||
at_root_has_selector: false,
|
at_root_has_selector: false,
|
||||||
extender: &mut Extender::new(empty_span),
|
extender: &mut Extender::new(empty_span),
|
||||||
|
content_scopes: &mut Scopes::new(),
|
||||||
}
|
}
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| raw_to_parse_error(&map, *e).to_string())?;
|
.map_err(|e| raw_to_parse_error(&map, *e).to_string())?;
|
||||||
|
@ -357,6 +357,10 @@ impl<'a> Parser<'a> {
|
|||||||
mut args: CallArgs,
|
mut args: CallArgs,
|
||||||
) -> SassResult<Scope> {
|
) -> SassResult<Scope> {
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
|
if fn_args.0.is_empty() {
|
||||||
|
args.max_args(0)?;
|
||||||
|
return Ok(scope);
|
||||||
|
}
|
||||||
self.scopes.enter_new_scope();
|
self.scopes.enter_new_scope();
|
||||||
for (idx, arg) in fn_args.0.iter_mut().enumerate() {
|
for (idx, arg) in fn_args.0.iter_mut().enumerate() {
|
||||||
if arg.is_variadic {
|
if arg.is_variadic {
|
||||||
|
@ -51,6 +51,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_stmt()?;
|
.parse_stmt()?;
|
||||||
} else {
|
} else {
|
||||||
@ -108,6 +109,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_stmt()?;
|
.parse_stmt()?;
|
||||||
} else {
|
} else {
|
||||||
@ -134,6 +136,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_stmt();
|
.parse_stmt();
|
||||||
}
|
}
|
||||||
@ -312,6 +315,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?;
|
.parse()?;
|
||||||
if !these_stmts.is_empty() {
|
if !these_stmts.is_empty() {
|
||||||
@ -332,6 +336,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?,
|
.parse()?,
|
||||||
);
|
);
|
||||||
@ -380,6 +385,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?;
|
.parse()?;
|
||||||
if !these_stmts.is_empty() {
|
if !these_stmts.is_empty() {
|
||||||
@ -400,6 +406,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?,
|
.parse()?,
|
||||||
);
|
);
|
||||||
@ -496,6 +503,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?;
|
.parse()?;
|
||||||
if !these_stmts.is_empty() {
|
if !these_stmts.is_empty() {
|
||||||
@ -516,6 +524,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?,
|
.parse()?,
|
||||||
);
|
);
|
||||||
|
@ -106,6 +106,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: false,
|
at_root: false,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?;
|
.parse()?;
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse();
|
.parse();
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
})
|
})
|
||||||
.parse_keyframes_selector()?;
|
.parse_keyframes_selector()?;
|
||||||
|
|
||||||
@ -193,6 +194,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: false,
|
at_root: false,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_stmt()?;
|
.parse_stmt()?;
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::mem;
|
||||||
|
|
||||||
use codemap::Spanned;
|
use codemap::Spanned;
|
||||||
|
|
||||||
use peekmore::PeekMore;
|
use peekmore::PeekMore;
|
||||||
@ -6,7 +8,6 @@ use crate::{
|
|||||||
args::{CallArgs, FuncArgs},
|
args::{CallArgs, FuncArgs},
|
||||||
atrule::{Content, Mixin},
|
atrule::{Content, Mixin},
|
||||||
error::SassResult,
|
error::SassResult,
|
||||||
scope::Scopes,
|
|
||||||
utils::read_until_closing_curly_brace,
|
utils::read_until_closing_curly_brace,
|
||||||
Token,
|
Token,
|
||||||
};
|
};
|
||||||
@ -121,30 +122,32 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let scope = self.eval_args(fn_args, args)?;
|
let scope = self.eval_args(fn_args, args)?;
|
||||||
|
|
||||||
let mut new_scope = Scopes::new();
|
let mut new_scope = std::mem::take(self.content_scopes);
|
||||||
let mut entered_scope = false;
|
|
||||||
if declared_at_root {
|
|
||||||
new_scope.enter_scope(scope);
|
|
||||||
} else {
|
|
||||||
entered_scope = true;
|
|
||||||
self.scopes.enter_scope(scope);
|
|
||||||
};
|
|
||||||
|
|
||||||
self.content.push(Content {
|
self.content.push(Content {
|
||||||
content,
|
content,
|
||||||
content_args,
|
content_args,
|
||||||
scopes: self.scopes.clone(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut scopes = if declared_at_root {
|
||||||
|
mem::take(&mut new_scope)
|
||||||
|
} else {
|
||||||
|
mem::take(self.scopes)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut content_scopes = if declared_at_root {
|
||||||
|
mem::take(self.scopes)
|
||||||
|
} else {
|
||||||
|
mem::take(&mut new_scope)
|
||||||
|
};
|
||||||
|
|
||||||
|
scopes.enter_scope(scope);
|
||||||
|
|
||||||
let body = Parser {
|
let body = Parser {
|
||||||
toks: &mut body.into_iter().peekmore(),
|
toks: &mut body.into_iter().peekmore(),
|
||||||
map: self.map,
|
map: self.map,
|
||||||
path: self.path,
|
path: self.path,
|
||||||
scopes: if declared_at_root {
|
scopes: &mut scopes,
|
||||||
&mut new_scope
|
|
||||||
} else {
|
|
||||||
self.scopes
|
|
||||||
},
|
|
||||||
global_scope: self.global_scope,
|
global_scope: self.global_scope,
|
||||||
super_selectors: self.super_selectors,
|
super_selectors: self.super_selectors,
|
||||||
span_before: self.span_before,
|
span_before: self.span_before,
|
||||||
@ -153,12 +156,18 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: false,
|
at_root: false,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: &mut content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?;
|
.parse()?;
|
||||||
|
|
||||||
self.content.pop();
|
self.content.pop();
|
||||||
if entered_scope {
|
if declared_at_root {
|
||||||
self.scopes.exit_scope();
|
*self.scopes = content_scopes;
|
||||||
|
*self.content_scopes = scopes;
|
||||||
|
} else {
|
||||||
|
scopes.exit_scope();
|
||||||
|
*self.scopes = scopes;
|
||||||
|
*self.content_scopes = content_scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(body)
|
Ok(body)
|
||||||
@ -173,19 +182,14 @@ impl<'a> Parser<'a> {
|
|||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scope = self
|
|
||||||
.content
|
|
||||||
.last()
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(Content::new)
|
|
||||||
.scopes;
|
|
||||||
if let Some(Token { kind: '(', .. }) = self.toks.peek() {
|
if let Some(Token { kind: '(', .. }) = self.toks.peek() {
|
||||||
self.toks.next();
|
self.toks.next();
|
||||||
let args = self.parse_call_args()?;
|
let args = self.parse_call_args()?;
|
||||||
if let Some(Some(content_args)) = self.content.last().map(|v| v.content_args.clone()) {
|
if let Some(Some(content_args)) = self.content.last().map(|v| v.content_args.clone()) {
|
||||||
args.max_args(content_args.len())?;
|
args.max_args(content_args.len())?;
|
||||||
|
|
||||||
scope.merge(self.eval_args(content_args, args)?);
|
let scope = self.eval_args(content_args, args)?;
|
||||||
|
self.content_scopes.merge(scope);
|
||||||
} else {
|
} else {
|
||||||
args.max_args(0)?;
|
args.max_args(0)?;
|
||||||
}
|
}
|
||||||
@ -197,7 +201,7 @@ impl<'a> Parser<'a> {
|
|||||||
toks: &mut body.into_iter().peekmore(),
|
toks: &mut body.into_iter().peekmore(),
|
||||||
map: self.map,
|
map: self.map,
|
||||||
path: self.path,
|
path: self.path,
|
||||||
scopes: &mut scope,
|
scopes: self.content_scopes,
|
||||||
global_scope: self.global_scope,
|
global_scope: self.global_scope,
|
||||||
super_selectors: self.super_selectors,
|
super_selectors: self.super_selectors,
|
||||||
span_before: self.span_before,
|
span_before: self.span_before,
|
||||||
@ -206,6 +210,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.scopes,
|
||||||
}
|
}
|
||||||
.parse()?
|
.parse()?
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,6 +70,7 @@ pub(crate) struct Parser<'a> {
|
|||||||
pub path: &'a Path,
|
pub path: &'a Path,
|
||||||
pub global_scope: &'a mut Scope,
|
pub global_scope: &'a mut Scope,
|
||||||
pub scopes: &'a mut Scopes,
|
pub scopes: &'a mut Scopes,
|
||||||
|
pub content_scopes: &'a mut Scopes,
|
||||||
pub super_selectors: &'a mut NeverEmptyVec<Selector>,
|
pub super_selectors: &'a mut NeverEmptyVec<Selector>,
|
||||||
pub span_before: Span,
|
pub span_before: Span,
|
||||||
pub content: &'a mut Vec<Content>,
|
pub content: &'a mut Vec<Content>,
|
||||||
@ -357,6 +358,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
},
|
},
|
||||||
allows_parent,
|
allows_parent,
|
||||||
true,
|
true,
|
||||||
@ -583,6 +585,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: false,
|
at_root: false,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_stmt()?;
|
.parse_stmt()?;
|
||||||
|
|
||||||
@ -649,6 +652,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: true,
|
at_root: true,
|
||||||
at_root_has_selector,
|
at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?
|
.parse()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -688,6 +692,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_selector(false, true, String::new())?;
|
.parse_selector(false, true, String::new())?;
|
||||||
|
|
||||||
@ -764,6 +769,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: false,
|
at_root: false,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse()?;
|
.parse()?;
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ impl<'a> Parser<'a> {
|
|||||||
at_root: self.at_root,
|
at_root: self.at_root,
|
||||||
at_root_has_selector: self.at_root_has_selector,
|
at_root_has_selector: self.at_root_has_selector,
|
||||||
extender: self.extender,
|
extender: self.extender,
|
||||||
|
content_scopes: self.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_value()
|
.parse_value()
|
||||||
}
|
}
|
||||||
|
@ -444,6 +444,7 @@ impl Value {
|
|||||||
at_root: parser.at_root,
|
at_root: parser.at_root,
|
||||||
at_root_has_selector: parser.at_root_has_selector,
|
at_root_has_selector: parser.at_root_has_selector,
|
||||||
extender: parser.extender,
|
extender: parser.extender,
|
||||||
|
content_scopes: parser.content_scopes,
|
||||||
}
|
}
|
||||||
.parse_selector(allows_parent, true, String::new())
|
.parse_selector(allows_parent, true, String::new())
|
||||||
}
|
}
|
||||||
|
@ -399,3 +399,30 @@ test!(
|
|||||||
}",
|
}",
|
||||||
"a {\n color: foo;\n color: bar;\n}\n"
|
"a {\n color: foo;\n color: bar;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
three_depth_of_content,
|
||||||
|
"@mixin foo($arg) {
|
||||||
|
@include bar {
|
||||||
|
color: $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin bar {
|
||||||
|
@include baz {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin baz {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin font-size($value) {
|
||||||
|
@include foo($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@include font-size(1rem);
|
||||||
|
}",
|
||||||
|
"a {\n color: 1rem;\n}\n"
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user