Merge pull request #1438 from sass/extend-bugs

Fix a couple bugs with @extend
This commit is contained in:
Natalie Weizenbaum 2021-08-16 22:01:32 +00:00 committed by GitHub
commit 390deed540
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 21 deletions

View File

@ -13,6 +13,9 @@
* Properly parse backslash escapes within `url()` expressions.
* Fix a couple bugs where `@extend`s could be marked as unsatisfied when
multiple identical `@extend`s extended selectors across `@use` rules.
### Command Line Interface
* Strip CRLF newlines from snippets of the original stylesheet that are included

View File

@ -409,7 +409,7 @@ class ExtensionStore {
/// Extends [this] with all the extensions in [extensions].
///
/// These extensions will extend all selectors already in [this], but they
/// will *not* extend other extensions from [extenders].
/// will *not* extend other extensions from [extensionStores].
void addExtensions(Iterable<ExtensionStore> extensionStores) {
// Extensions already in [this] whose extenders are extended by
// [extensions], and thus which need to be updated.
@ -445,21 +445,18 @@ class ExtensionStore {
// Add [newSources] to [_extensions].
var existingSources = _extensions[target];
if (existingSources == null) {
_extensions[target] = newSources;
_extensions[target] = Map.of(newSources);
if (extensionsForTarget != null || selectorsForTarget != null) {
(newExtensions ??= {})[target] = newSources;
(newExtensions ??= {})[target] = Map.of(newSources);
}
} else {
newSources.forEach((extender, extension) {
// If [extender] already extends [target] in [_extensions], we don't
// need to re-run the extension.
if (existingSources.containsKey(extender)) return;
existingSources[extender] = extension;
extension = existingSources.putOrMerge(
extender, extension, MergedExtension.merge);
if (extensionsForTarget != null || selectorsForTarget != null) {
(newExtensions ??= {})
.putIfAbsent(target, () => {})
.putIfAbsent(extender, () => extension);
(newExtensions ??= {}).putIfAbsent(target, () => {})[extender] =
extension;
}
});
}

View File

@ -187,11 +187,11 @@ JsError _wrapException(Object exception) {
var url = exception.span.sourceUrl;
if (url == null) {
file = 'stdin';
} else if (url.scheme == 'file') {
file = p.fromUri(url);
} else {
file = url.toString();
}
} else if (url.scheme == 'file') {
file = p.fromUri(url);
} else {
file = url.toString();
}
return _newRenderError(exception.toString().replaceFirst("Error: ", ""),
line: exception.span.start.line + 1,

View File

@ -403,3 +403,15 @@ extension SpanExtensions on FileSpan {
: file.span(this.start.offset + start, this.start.offset + end + 1);
}
}
extension MapExtension<K, V> on Map<K, V> {
/// If [this] doesn't contain the given [key], sets that key to [value] and
/// returns it.
///
/// Otherwise, calls [merge] with the existing value and [value] and sets
/// [key] to the result.
V putOrMerge(K key, V value, V Function(V oldValue, V newValue) merge) =>
containsKey(key)
? this[key] = merge(this[key]!, value)
: this[key] = value;
}

View File

@ -706,14 +706,14 @@ void main() {
});
test("it occurs in a file with a custom URL scheme", () {
var error =
renderSyncError(RenderOptions(
data: "@import 'foo:bar'",
importer: allowInterop(expectAsync2((String _, void __) {
return NodeImporterResult(contents: '@error "oh no";');
var error = renderSyncError(RenderOptions(
data: "@import 'foo:bar'",
importer: allowInterop(expectAsync2((String _, void __) {
return NodeImporterResult(contents: '@error "oh no";');
}))));
expect(error,
expect(
error,
toStringAndMessageEqual("\"oh no\"\n"
"\n"
"1 │ @error \"oh no\";\n"