naively cache imports in certain cases

This commit is contained in:
connorskees 2023-01-11 14:59:28 +00:00
parent 3cb5e66fda
commit 95efc582b5
2 changed files with 28 additions and 0 deletions

View File

@ -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

View File

@ -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);
} }