Skip to content

Commit 390deed

Browse files
authored
Merge pull request #1438 from sass/extend-bugs
Fix a couple bugs with @extend
2 parents 2a03907 + 707db69 commit 390deed

File tree

5 files changed

+33
-21
lines changed

5 files changed

+33
-21
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
* Properly parse backslash escapes within `url()` expressions.
1515

16+
* Fix a couple bugs where `@extend`s could be marked as unsatisfied when
17+
multiple identical `@extend`s extended selectors across `@use` rules.
18+
1619
### Command Line Interface
1720

1821
* Strip CRLF newlines from snippets of the original stylesheet that are included

lib/src/extend/extension_store.dart

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ class ExtensionStore {
409409
/// Extends [this] with all the extensions in [extensions].
410410
///
411411
/// These extensions will extend all selectors already in [this], but they
412-
/// will *not* extend other extensions from [extenders].
412+
/// will *not* extend other extensions from [extensionStores].
413413
void addExtensions(Iterable<ExtensionStore> extensionStores) {
414414
// Extensions already in [this] whose extenders are extended by
415415
// [extensions], and thus which need to be updated.
@@ -445,21 +445,18 @@ class ExtensionStore {
445445
// Add [newSources] to [_extensions].
446446
var existingSources = _extensions[target];
447447
if (existingSources == null) {
448-
_extensions[target] = newSources;
448+
_extensions[target] = Map.of(newSources);
449449
if (extensionsForTarget != null || selectorsForTarget != null) {
450-
(newExtensions ??= {})[target] = newSources;
450+
(newExtensions ??= {})[target] = Map.of(newSources);
451451
}
452452
} else {
453453
newSources.forEach((extender, extension) {
454-
// If [extender] already extends [target] in [_extensions], we don't
455-
// need to re-run the extension.
456-
if (existingSources.containsKey(extender)) return;
457-
existingSources[extender] = extension;
454+
extension = existingSources.putOrMerge(
455+
extender, extension, MergedExtension.merge);
458456

459457
if (extensionsForTarget != null || selectorsForTarget != null) {
460-
(newExtensions ??= {})
461-
.putIfAbsent(target, () => {})
462-
.putIfAbsent(extender, () => extension);
458+
(newExtensions ??= {}).putIfAbsent(target, () => {})[extender] =
459+
extension;
463460
}
464461
});
465462
}

lib/src/node.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ JsError _wrapException(Object exception) {
187187
var url = exception.span.sourceUrl;
188188
if (url == null) {
189189
file = 'stdin';
190-
} else if (url.scheme == 'file') {
191-
file = p.fromUri(url);
192-
} else {
193-
file = url.toString();
194-
}
190+
} else if (url.scheme == 'file') {
191+
file = p.fromUri(url);
192+
} else {
193+
file = url.toString();
194+
}
195195

196196
return _newRenderError(exception.toString().replaceFirst("Error: ", ""),
197197
line: exception.span.start.line + 1,

lib/src/utils.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,15 @@ extension SpanExtensions on FileSpan {
403403
: file.span(this.start.offset + start, this.start.offset + end + 1);
404404
}
405405
}
406+
407+
extension MapExtension<K, V> on Map<K, V> {
408+
/// If [this] doesn't contain the given [key], sets that key to [value] and
409+
/// returns it.
410+
///
411+
/// Otherwise, calls [merge] with the existing value and [value] and sets
412+
/// [key] to the result.
413+
V putOrMerge(K key, V value, V Function(V oldValue, V newValue) merge) =>
414+
containsKey(key)
415+
? this[key] = merge(this[key]!, value)
416+
: this[key] = value;
417+
}

test/node_api/importer_test.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -706,14 +706,14 @@ void main() {
706706
});
707707

708708
test("it occurs in a file with a custom URL scheme", () {
709-
var error =
710-
renderSyncError(RenderOptions(
711-
data: "@import 'foo:bar'",
712-
importer: allowInterop(expectAsync2((String _, void __) {
713-
return NodeImporterResult(contents: '@error "oh no";');
709+
var error = renderSyncError(RenderOptions(
710+
data: "@import 'foo:bar'",
711+
importer: allowInterop(expectAsync2((String _, void __) {
712+
return NodeImporterResult(contents: '@error "oh no";');
714713
}))));
715714

716-
expect(error,
715+
expect(
716+
error,
717717
toStringAndMessageEqual("\"oh no\"\n"
718718
" ╷\n"
719719
"1 │ @error \"oh no\";\n"

0 commit comments

Comments
 (0)