dart-sass icon indicating copy to clipboard operation
dart-sass copied to clipboard

Crash when @importing an upstream file with a top level @include that outputs a declaration only when that upstream file @uses another file

Open Goodwine opened this issue 6 months ago • 3 comments

Example (HRX)

<==> input.scss
.foo {
  @import 'upstream';
}

<==> upstream.scss
@use 'other';

@mixin a() {
  b: c;
}

@include a;

<==> _other.scss
// empty, it doesn't matter

This crashes because evaluate.dart checks for the declaration's "parent's parent". And I guess the reference isn't there. https://github.com/sass/dart-sass/blob/a42380fcf817e8765d1237c1bb5bfbd98ee73ad9/lib/src/visitor/evaluate.dart#L1345

Interestingly, this doesn't crash if we...:

  • remove the @use rule
  • replace @use for a built-in module like @use 'sass:math'
  • wrap @include a with &{}
  • remove the wrapping rule .foo{} (it does fail because the delcarataion ends up without a container, but it at least it doesn't crash)

Goodwine avatar Jun 13 '25 23:06 Goodwine

I think I found out why. There is an if() which replaces _parent with _root when the user declares any @use that isn't a built-in module

https://github.com/sass/dart-sass/blob/a42380fcf817e8765d1237c1bb5bfbd98ee73ad9/lib/src/visitor/evaluate.dart#L1904-L1909

I guess we need to detect that. But I'm not sure whether this should throw an error or not 🤔

Goodwine avatar Jun 14 '25 00:06 Goodwine

The @include a should be an error. We should probably explicitly check that _parent != root when evaluating a declaration.

nex3 avatar Jun 14 '25 00:06 nex3

discussed this offline a bit more. In this case @include a shouldn't have thrown an error because the @import was nested within a style rule. It should (and it does) throw an error when a top level @include produces a declaration. We just need to be able to catch this specific case

Goodwine avatar Jun 16 '25 21:06 Goodwine