naively cache imports in certain cases
This commit is contained in:
parent
3cb5e66fda
commit
95efc582b5
@ -5,6 +5,10 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
# 0.12.2 (unreleased)
|
||||||
|
|
||||||
|
- implement an import cache, significantly improving the performance of certain pathological cases
|
||||||
|
|
||||||
# 0.12.1
|
# 0.12.1
|
||||||
|
|
||||||
- add `grass::include!` macro to make it easier to include CSS at compile time
|
- add `grass::include!` macro to make it easier to include CSS at compile time
|
||||||
|
@ -119,6 +119,11 @@ pub(crate) struct Visitor<'a> {
|
|||||||
pub map: &'a mut CodeMap,
|
pub map: &'a mut CodeMap,
|
||||||
// todo: remove
|
// todo: remove
|
||||||
span_before: Span,
|
span_before: Span,
|
||||||
|
import_cache: BTreeMap<PathBuf, StyleSheet>,
|
||||||
|
/// As a simple heuristic, we don't cache the results of an import unless it
|
||||||
|
/// has been seen in the past. In the majority of cases, files are imported
|
||||||
|
/// at most once.
|
||||||
|
files_seen: BTreeSet<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visitor<'a> {
|
impl<'a> Visitor<'a> {
|
||||||
@ -153,6 +158,8 @@ impl<'a> Visitor<'a> {
|
|||||||
options,
|
options,
|
||||||
span_before,
|
span_before,
|
||||||
map,
|
map,
|
||||||
|
import_cache: BTreeMap::new(),
|
||||||
|
files_seen: BTreeSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,6 +829,16 @@ impl<'a> Visitor<'a> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> SassResult<StyleSheet> {
|
) -> SassResult<StyleSheet> {
|
||||||
if let Some(name) = self.find_import(url.as_ref()) {
|
if let Some(name) = self.find_import(url.as_ref()) {
|
||||||
|
// assumption: most users use regular file paths for their imports.
|
||||||
|
// we do support importing syntactically invalid paths and paths that
|
||||||
|
// do not exist through the `Options::fs` API, so we fallback to the
|
||||||
|
// original name if necessary
|
||||||
|
let canonical = std::fs::canonicalize(&name).unwrap_or_else(|_| name.to_path_buf());
|
||||||
|
|
||||||
|
if let Some(style_sheet) = self.import_cache.get(&canonical) {
|
||||||
|
return Ok(style_sheet.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let file = self.map.add_file(
|
let file = self.map.add_file(
|
||||||
name.to_string_lossy().into(),
|
name.to_string_lossy().into(),
|
||||||
String::from_utf8(self.options.fs.read(&name)?)?,
|
String::from_utf8(self.options.fs.read(&name)?)?,
|
||||||
@ -835,6 +852,13 @@ impl<'a> Visitor<'a> {
|
|||||||
|
|
||||||
self.flags
|
self.flags
|
||||||
.set(ContextFlags::IS_USE_ALLOWED, old_is_use_allowed);
|
.set(ContextFlags::IS_USE_ALLOWED, old_is_use_allowed);
|
||||||
|
|
||||||
|
if self.files_seen.contains(&canonical) {
|
||||||
|
self.import_cache.insert(canonical, style_sheet.clone());
|
||||||
|
} else {
|
||||||
|
self.files_seen.insert(canonical);
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(style_sheet);
|
return Ok(style_sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user