diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b2ccc65f..68ae2fe45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.89.3 + +* Fixed a crash when `@import` was nested in a style rule and loaded a Sass file + that `@use`s a non-built-in module and a top-level `@include` that emits + declarations. + ## 1.89.2 ### Embedded Host diff --git a/lib/src/visitor/async_evaluate.dart b/lib/src/visitor/async_evaluate.dart index c1db0e72e..3938734b4 100644 --- a/lib/src/visitor/async_evaluate.dart +++ b/lib/src/visitor/async_evaluate.dart @@ -208,6 +208,12 @@ final class _EvaluateVisitor ModifiableCssParentNode? __parent; + /// The original parent node for a stylesheet that was loaded with `@import`. + /// + /// This value is only set when a file uses `@import` in combination with + /// non-built-in Sass modules. + ModifiableCssParentNode? _importParent; + /// The name of the current declaration parent. String? _declarationName; @@ -1321,7 +1327,12 @@ final class _EvaluateVisitor } Future visitDeclaration(Declaration node) async { - if (_styleRule == null && !_inUnknownAtRule && !_inKeyframes) { + // If a stylesheet is @imported inside a style rule, declarations from that + // imported sheet are parented by the outer style rule. + var parent = _parent.parent == null ? _importParent : _parent; + + if ((_styleRule == null && !_inUnknownAtRule && !_inKeyframes) || + parent == null) { throw _exception( "Declarations may only be used within style rules.", node.span, @@ -1334,14 +1345,14 @@ final class _EvaluateVisitor ); } - var siblings = _parent.parent!.children; + var siblings = parent.parent?.children ?? []; var interleavedRules = []; - if (siblings.last != _parent && - // Reproduce this condition from [_warn] so that we don't add anything to - // [interleavedRules] for declarations in dependencies. + if (siblings.last != parent && + // Reproduce this condition from [_warn] so that we don't add anything + // to [interleavedRules] for declarations in dependencies. !(_quietDeps && _inDependency)) { loop: - for (var sibling in siblings.skip(siblings.indexOf(_parent) + 1)) { + for (var sibling in siblings.skip(siblings.indexOf(parent) + 1)) { switch (sibling) { case CssComment(): continue loop; @@ -1387,7 +1398,7 @@ final class _EvaluateVisitor _isEmptyList(value) || // Custom properties are allowed to have empty values, per spec. name.value.startsWith('--')) { - _parent.addChild( + parent.addChild( ModifiableCssDeclaration( name, CssValue(value, expression.span), @@ -1895,6 +1906,7 @@ final class _EvaluateVisitor _stylesheet = stylesheet; if (loadsUserDefinedModules) { _root = ModifiableCssStylesheet(stylesheet.span); + _importParent = _parent; _parent = _root; _endOfImports = 0; _outOfOrderImports = null; @@ -1915,6 +1927,7 @@ final class _EvaluateVisitor if (loadsUserDefinedModules) { _root = oldRoot; _parent = oldParent; + _importParent = null; _endOfImports = oldEndOfImports; _outOfOrderImports = oldOutOfOrderImports; } diff --git a/lib/src/visitor/evaluate.dart b/lib/src/visitor/evaluate.dart index 5727e56aa..040f4d94c 100644 --- a/lib/src/visitor/evaluate.dart +++ b/lib/src/visitor/evaluate.dart @@ -5,7 +5,7 @@ // DO NOT EDIT. This file was generated from async_evaluate.dart. // See tool/grind/synchronize.dart for details. // -// Checksum: a3068d04660dd2bed34b884aa6e1a21d423dc4e5 +// Checksum: 0db2da7b7facb3c5c79cfba1d6829d18a5de5cdd // // ignore_for_file: unused_import @@ -216,6 +216,12 @@ final class _EvaluateVisitor ModifiableCssParentNode? __parent; + /// The original parent node for a stylesheet that was loaded with `@import`. + /// + /// This value is only set when a file uses `@import` in combination with + /// non-built-in Sass modules. + ModifiableCssParentNode? _importParent; + /// The name of the current declaration parent. String? _declarationName; @@ -1329,7 +1335,12 @@ final class _EvaluateVisitor } Value? visitDeclaration(Declaration node) { - if (_styleRule == null && !_inUnknownAtRule && !_inKeyframes) { + // If a stylesheet is @imported inside a style rule, declarations from that + // imported sheet are parented by the outer style rule. + var parent = _parent.parent == null ? _importParent : _parent; + + if ((_styleRule == null && !_inUnknownAtRule && !_inKeyframes) || + parent == null) { throw _exception( "Declarations may only be used within style rules.", node.span, @@ -1342,14 +1353,14 @@ final class _EvaluateVisitor ); } - var siblings = _parent.parent!.children; + var siblings = parent.parent?.children ?? []; var interleavedRules = []; - if (siblings.last != _parent && - // Reproduce this condition from [_warn] so that we don't add anything to - // [interleavedRules] for declarations in dependencies. + if (siblings.last != parent && + // Reproduce this condition from [_warn] so that we don't add anything + // to [interleavedRules] for declarations in dependencies. !(_quietDeps && _inDependency)) { loop: - for (var sibling in siblings.skip(siblings.indexOf(_parent) + 1)) { + for (var sibling in siblings.skip(siblings.indexOf(parent) + 1)) { switch (sibling) { case CssComment(): continue loop; @@ -1395,7 +1406,7 @@ final class _EvaluateVisitor _isEmptyList(value) || // Custom properties are allowed to have empty values, per spec. name.value.startsWith('--')) { - _parent.addChild( + parent.addChild( ModifiableCssDeclaration( name, CssValue(value, expression.span), @@ -1903,6 +1914,7 @@ final class _EvaluateVisitor _stylesheet = stylesheet; if (loadsUserDefinedModules) { _root = ModifiableCssStylesheet(stylesheet.span); + _importParent = _parent; _parent = _root; _endOfImports = 0; _outOfOrderImports = null; @@ -1923,6 +1935,7 @@ final class _EvaluateVisitor if (loadsUserDefinedModules) { _root = oldRoot; _parent = oldParent; + _importParent = null; _endOfImports = oldEndOfImports; _outOfOrderImports = oldOutOfOrderImports; } diff --git a/pkg/sass-parser/CHANGELOG.md b/pkg/sass-parser/CHANGELOG.md index ef9e27284..1c1862ee3 100644 --- a/pkg/sass-parser/CHANGELOG.md +++ b/pkg/sass-parser/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.25 + +* No user-visible changes. + ## 0.4.24 * No user-visible changes. diff --git a/pkg/sass-parser/package.json b/pkg/sass-parser/package.json index f3d816655..128c4b1e2 100644 --- a/pkg/sass-parser/package.json +++ b/pkg/sass-parser/package.json @@ -1,6 +1,6 @@ { "name": "sass-parser", - "version": "0.4.24", + "version": "0.4.25", "description": "A PostCSS-compatible wrapper of the official Sass parser", "repository": "sass/sass", "author": "Google Inc.", diff --git a/pkg/sass_api/CHANGELOG.md b/pkg/sass_api/CHANGELOG.md index e034f36f9..cb5bdf3c5 100644 --- a/pkg/sass_api/CHANGELOG.md +++ b/pkg/sass_api/CHANGELOG.md @@ -1,3 +1,7 @@ +## 15.7.2 + +* No user-visible changes. + ## 15.7.1 * No user-visible changes. diff --git a/pkg/sass_api/pubspec.yaml b/pkg/sass_api/pubspec.yaml index a0ad29aca..787bb1575 100644 --- a/pkg/sass_api/pubspec.yaml +++ b/pkg/sass_api/pubspec.yaml @@ -2,7 +2,7 @@ name: sass_api # Note: Every time we add a new Sass AST node, we need to bump the *major* # version because it's a breaking change for anyone who's implementing the # visitor interface(s). -version: 15.7.1 +version: 15.7.2 description: Additional APIs for Dart Sass. homepage: https://github.com/sass/dart-sass @@ -10,7 +10,7 @@ environment: sdk: ">=3.6.0 <4.0.0" dependencies: - sass: 1.89.2 + sass: 1.89.3 dev_dependencies: dartdoc: ^8.0.14 diff --git a/pubspec.yaml b/pubspec.yaml index 039be9860..aada25374 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.89.2 +version: 1.89.3 description: A Sass implementation in Dart. homepage: https://github.com/sass/dart-sass