mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-30 04:39:03 +01:00
Cache relative import results as well as absolute ones
This dramatically improves the performance of a sample app using the Carbon design system, and should generally improve apps that have a lot of repeated @imports of library files. It's possible we can back this out if it's not pulling its weight once we no longer support @import.
This commit is contained in:
parent
6069708a83
commit
d13a38ed19
@ -33,16 +33,31 @@ class AsyncImportCache {
|
||||
///
|
||||
/// This map's values are the same as the return value of [canonicalize].
|
||||
///
|
||||
/// This cache isn't used for relative imports, because they're
|
||||
/// context-dependent.
|
||||
final Map<Tuple2<Uri, bool>, Tuple3<AsyncImporter, Uri, Uri>?>
|
||||
_canonicalizeCache;
|
||||
/// This cache isn't used for relative imports, because they depend on the
|
||||
/// specific base importer. That's stored separately in
|
||||
/// [_relativeCanonicalizeCache].
|
||||
final _canonicalizeCache =
|
||||
<Tuple2<Uri, bool>, Tuple3<AsyncImporter, Uri, Uri>?>{};
|
||||
|
||||
/// The canonicalized URLs for each non-canonical URL that's resolved using a
|
||||
/// relative importer.
|
||||
///
|
||||
/// The map's keys have four parts:
|
||||
///
|
||||
/// 1. The URL passed to [canonicalize] (the same as in [_canonicalizeCache]).
|
||||
/// 2. Whether the canonicalization is for an `@import` rule.
|
||||
/// 3. The `baseImporter` passed to [canonicalize].
|
||||
/// 4. The `baseUrl` passed to [canonicalize].
|
||||
///
|
||||
/// The map's values are the same as the return value of [canonicalize].
|
||||
final _relativeCanonicalizeCache = <Tuple4<Uri, bool, AsyncImporter, Uri?>,
|
||||
Tuple3<AsyncImporter, Uri, Uri>?>{};
|
||||
|
||||
/// The parsed stylesheets for each canonicalized import URL.
|
||||
final Map<Uri, Stylesheet?> _importCache;
|
||||
final _importCache = <Uri, Stylesheet?>{};
|
||||
|
||||
/// The import results for each canonicalized import URL.
|
||||
final Map<Uri, ImporterResult> _resultsCache;
|
||||
final _resultsCache = <Uri, ImporterResult>{};
|
||||
|
||||
/// Creates an import cache that resolves imports using [importers].
|
||||
///
|
||||
@ -67,18 +82,12 @@ class AsyncImportCache {
|
||||
PackageConfig? packageConfig,
|
||||
Logger? logger})
|
||||
: _importers = _toImporters(importers, loadPaths, packageConfig),
|
||||
_logger = logger ?? const Logger.stderr(),
|
||||
_canonicalizeCache = {},
|
||||
_importCache = {},
|
||||
_resultsCache = {};
|
||||
_logger = logger ?? const Logger.stderr();
|
||||
|
||||
/// Creates an import cache without any globally-available importers.
|
||||
AsyncImportCache.none({Logger? logger})
|
||||
: _importers = const [],
|
||||
_logger = logger ?? const Logger.stderr(),
|
||||
_canonicalizeCache = {},
|
||||
_importCache = {},
|
||||
_resultsCache = {};
|
||||
_logger = logger ?? const Logger.stderr();
|
||||
|
||||
/// Converts the user's [importers], [loadPaths], and [packageConfig]
|
||||
/// options into a single list of importers.
|
||||
@ -113,12 +122,16 @@ class AsyncImportCache {
|
||||
Uri? baseUrl,
|
||||
bool forImport = false}) async {
|
||||
if (baseImporter != null) {
|
||||
var resolvedUrl = baseUrl?.resolveUri(url) ?? url;
|
||||
var canonicalUrl =
|
||||
await _canonicalize(baseImporter, resolvedUrl, forImport);
|
||||
if (canonicalUrl != null) {
|
||||
return Tuple3(baseImporter, canonicalUrl, resolvedUrl);
|
||||
}
|
||||
var relativeResult = await putIfAbsentAsync(_relativeCanonicalizeCache,
|
||||
Tuple4(url, forImport, baseImporter, baseUrl), () async {
|
||||
var resolvedUrl = baseUrl?.resolveUri(url) ?? url;
|
||||
var canonicalUrl =
|
||||
await _canonicalize(baseImporter, resolvedUrl, forImport);
|
||||
if (canonicalUrl != null) {
|
||||
return Tuple3(baseImporter, canonicalUrl, resolvedUrl);
|
||||
}
|
||||
});
|
||||
if (relativeResult != null) return relativeResult;
|
||||
}
|
||||
|
||||
return await putIfAbsentAsync(_canonicalizeCache, Tuple2(url, forImport),
|
||||
@ -236,6 +249,14 @@ Relative canonical URLs are deprecated and will eventually be disallowed.
|
||||
void clearCanonicalize(Uri url) {
|
||||
_canonicalizeCache.remove(Tuple2(url, false));
|
||||
_canonicalizeCache.remove(Tuple2(url, true));
|
||||
|
||||
var relativeKeysToClear = [
|
||||
for (var key in _relativeCanonicalizeCache.keys)
|
||||
if (key.item1 == url) key
|
||||
];
|
||||
for (var key in relativeKeysToClear) {
|
||||
_relativeCanonicalizeCache.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the cached parse tree for the stylesheet with the given
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_import_cache.dart.
|
||||
// See tool/grind/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: b3b80fe96623c1579809528e46d9c75b87bf82ea
|
||||
// Checksum: 3e290e40f4576be99217ddfbd7a76c4d38721af1
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
@ -40,15 +40,30 @@ class ImportCache {
|
||||
///
|
||||
/// This map's values are the same as the return value of [canonicalize].
|
||||
///
|
||||
/// This cache isn't used for relative imports, because they're
|
||||
/// context-dependent.
|
||||
final Map<Tuple2<Uri, bool>, Tuple3<Importer, Uri, Uri>?> _canonicalizeCache;
|
||||
/// This cache isn't used for relative imports, because they depend on the
|
||||
/// specific base importer. That's stored separately in
|
||||
/// [_relativeCanonicalizeCache].
|
||||
final _canonicalizeCache = <Tuple2<Uri, bool>, Tuple3<Importer, Uri, Uri>?>{};
|
||||
|
||||
/// The canonicalized URLs for each non-canonical URL that's resolved using a
|
||||
/// relative importer.
|
||||
///
|
||||
/// The map's keys have four parts:
|
||||
///
|
||||
/// 1. The URL passed to [canonicalize] (the same as in [_canonicalizeCache]).
|
||||
/// 2. Whether the canonicalization is for an `@import` rule.
|
||||
/// 3. The `baseImporter` passed to [canonicalize].
|
||||
/// 4. The `baseUrl` passed to [canonicalize].
|
||||
///
|
||||
/// The map's values are the same as the return value of [canonicalize].
|
||||
final _relativeCanonicalizeCache =
|
||||
<Tuple4<Uri, bool, Importer, Uri?>, Tuple3<Importer, Uri, Uri>?>{};
|
||||
|
||||
/// The parsed stylesheets for each canonicalized import URL.
|
||||
final Map<Uri, Stylesheet?> _importCache;
|
||||
final _importCache = <Uri, Stylesheet?>{};
|
||||
|
||||
/// The import results for each canonicalized import URL.
|
||||
final Map<Uri, ImporterResult> _resultsCache;
|
||||
final _resultsCache = <Uri, ImporterResult>{};
|
||||
|
||||
/// Creates an import cache that resolves imports using [importers].
|
||||
///
|
||||
@ -73,18 +88,12 @@ class ImportCache {
|
||||
PackageConfig? packageConfig,
|
||||
Logger? logger})
|
||||
: _importers = _toImporters(importers, loadPaths, packageConfig),
|
||||
_logger = logger ?? const Logger.stderr(),
|
||||
_canonicalizeCache = {},
|
||||
_importCache = {},
|
||||
_resultsCache = {};
|
||||
_logger = logger ?? const Logger.stderr();
|
||||
|
||||
/// Creates an import cache without any globally-available importers.
|
||||
ImportCache.none({Logger? logger})
|
||||
: _importers = const [],
|
||||
_logger = logger ?? const Logger.stderr(),
|
||||
_canonicalizeCache = {},
|
||||
_importCache = {},
|
||||
_resultsCache = {};
|
||||
_logger = logger ?? const Logger.stderr();
|
||||
|
||||
/// Converts the user's [importers], [loadPaths], and [packageConfig]
|
||||
/// options into a single list of importers.
|
||||
@ -117,11 +126,15 @@ class ImportCache {
|
||||
Tuple3<Importer, Uri, Uri>? canonicalize(Uri url,
|
||||
{Importer? baseImporter, Uri? baseUrl, bool forImport = false}) {
|
||||
if (baseImporter != null) {
|
||||
var resolvedUrl = baseUrl?.resolveUri(url) ?? url;
|
||||
var canonicalUrl = _canonicalize(baseImporter, resolvedUrl, forImport);
|
||||
if (canonicalUrl != null) {
|
||||
return Tuple3(baseImporter, canonicalUrl, resolvedUrl);
|
||||
}
|
||||
var relativeResult = _relativeCanonicalizeCache
|
||||
.putIfAbsent(Tuple4(url, forImport, baseImporter, baseUrl), () {
|
||||
var resolvedUrl = baseUrl?.resolveUri(url) ?? url;
|
||||
var canonicalUrl = _canonicalize(baseImporter, resolvedUrl, forImport);
|
||||
if (canonicalUrl != null) {
|
||||
return Tuple3(baseImporter, canonicalUrl, resolvedUrl);
|
||||
}
|
||||
});
|
||||
if (relativeResult != null) return relativeResult;
|
||||
}
|
||||
|
||||
return _canonicalizeCache.putIfAbsent(Tuple2(url, forImport), () {
|
||||
@ -235,6 +248,14 @@ Relative canonical URLs are deprecated and will eventually be disallowed.
|
||||
void clearCanonicalize(Uri url) {
|
||||
_canonicalizeCache.remove(Tuple2(url, false));
|
||||
_canonicalizeCache.remove(Tuple2(url, true));
|
||||
|
||||
var relativeKeysToClear = [
|
||||
for (var key in _relativeCanonicalizeCache.keys)
|
||||
if (key.item1 == url) key
|
||||
];
|
||||
for (var key in relativeKeysToClear) {
|
||||
_relativeCanonicalizeCache.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the cached parse tree for the stylesheet with the given
|
||||
|
Loading…
Reference in New Issue
Block a user