From 702a7ee7a18c0265f8f90ff1155268e477dd77cf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 6 Apr 2023 14:44:29 -0700 Subject: [PATCH 1/2] Fix the performance of selector span expansion (#1929) Instead of calling `SourceFile.getText()`, which creates string copies of a substantial subset of the text of the file every time, this directly accesses the file's underlying code units without doing any copies. Closes #1913 --- CHANGELOG.md | 2 ++ lib/src/interpolation_map.dart | 32 ++++++++++++++++---------------- pkg/sass_api/CHANGELOG.md | 4 ++++ pkg/sass_api/pubspec.yaml | 4 ++-- pubspec.yaml | 4 ++-- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ffc63e44..446755ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ * **Potentially breaking change:** Drop support for End-of-Life Node.js 12. +* Fix remaining cases for the performance regression introduced in 1.59.0. + ### Embedded Sass * The JS embedded host now loads files from the working directory when using the diff --git a/lib/src/interpolation_map.dart b/lib/src/interpolation_map.dart index eb52e4009..8cb81e09b 100644 --- a/lib/src/interpolation_map.dart +++ b/lib/src/interpolation_map.dart @@ -6,7 +6,6 @@ import 'dart:math' as math; import 'package:charcode/charcode.dart'; import 'package:source_span/source_span.dart'; -import 'package:string_scanner/string_scanner.dart'; import 'ast/sass.dart'; import 'util/character.dart'; @@ -125,21 +124,21 @@ class InterpolationMap { /// comment before the expression, but since it's only used for error /// reporting that's probably fine. int _expandInterpolationSpanLeft(FileLocation start) { - var source = start.file.getText(0, start.offset); + var source = start.file.codeUnits; var i = start.offset - 1; - while (true) { - var prev = source.codeUnitAt(i--); + while (i >= 0) { + var prev = source[i--]; if (prev == $lbrace) { - if (source.codeUnitAt(i) == $hash) break; + if (source[i] == $hash) break; } else if (prev == $slash) { - var second = source.codeUnitAt(i--); + var second = source[i--]; if (second == $asterisk) { while (true) { - var char = source.codeUnitAt(i--); + var char = source[i--]; if (char != $asterisk) continue; do { - char = source.codeUnitAt(i--); + char = source[i--]; } while (char == $asterisk); if (char == $slash) break; } @@ -153,21 +152,22 @@ class InterpolationMap { /// Given the end of a [FileSpan] covering an interpolated expression, returns /// the offset of the interpolation's closing `}`. int _expandInterpolationSpanRight(FileLocation end) { - var scanner = StringScanner(end.file.getText(end.offset)); - while (true) { - var next = scanner.readChar(); + var source = end.file.codeUnits; + var i = end.offset; + while (i < source.length) { + var next = source[i++]; if (next == $rbrace) break; if (next == $slash) { - var second = scanner.readChar(); + var second = source[i++]; if (second == $slash) { - while (!isNewline(scanner.readChar())) {} + while (!isNewline(source[i++])) {} } else if (second == $asterisk) { while (true) { - var char = scanner.readChar(); + var char = source[i++]; if (char != $asterisk) continue; do { - char = scanner.readChar(); + char = source[i++]; } while (char == $asterisk); if (char == $slash) break; } @@ -175,6 +175,6 @@ class InterpolationMap { } } - return end.offset + scanner.position; + return i; } } diff --git a/pkg/sass_api/CHANGELOG.md b/pkg/sass_api/CHANGELOG.md index 7a48adbe4..e251836b1 100644 --- a/pkg/sass_api/CHANGELOG.md +++ b/pkg/sass_api/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.2.0 + +* No user-visible changes. + ## 6.1.0 * No user-visible changes. diff --git a/pkg/sass_api/pubspec.yaml b/pkg/sass_api/pubspec.yaml index 039c65adf..a85600509 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: 6.1.0 +version: 6.2.0 description: Additional APIs for Dart Sass. homepage: https://github.com/sass/dart-sass @@ -10,7 +10,7 @@ environment: sdk: ">=2.17.0 <3.0.0" dependencies: - sass: 1.60.0 + sass: 1.61.0 dev_dependencies: dartdoc: ^5.0.0 diff --git a/pubspec.yaml b/pubspec.yaml index c79520d7d..1e967c589 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.61.0-dev +version: 1.61.0 description: A Sass implementation in Dart. homepage: https://github.com/sass/dart-sass @@ -23,7 +23,7 @@ dependencies: path: ^1.8.0 pub_semver: ^2.0.0 source_maps: ^0.10.10 - source_span: ^1.8.1 + source_span: ^1.10.0 stack_trace: ^1.10.0 stream_transform: ^2.0.0 string_scanner: ^1.1.0 From 283bdc00637082404bfb3a5b45186699e07381cd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 7 Apr 2023 16:29:57 -0700 Subject: [PATCH 2/2] Deprecate duplicate !global and !default declarations (#1931) See #604 See sass/sass#2607 --- CHANGELOG.md | 5 +++++ lib/src/deprecation.dart | 5 +++++ lib/src/parse/stylesheet.dart | 14 ++++++++++++++ pkg/sass_api/CHANGELOG.md | 4 ++++ pkg/sass_api/pubspec.yaml | 4 ++-- pubspec.yaml | 2 +- 6 files changed, 31 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 446755ebb..148981c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.62.0 + +* Deprecate the use of multiple `!global` or `!default` flags on the same + variable. This deprecation is named `duplicate-var-flags`. + ## 1.61.0 * **Potentially breaking change:** Drop support for End-of-Life Node.js 12. diff --git a/lib/src/deprecation.dart b/lib/src/deprecation.dart index 25526c510..0d913424e 100644 --- a/lib/src/deprecation.dart +++ b/lib/src/deprecation.dart @@ -54,6 +54,11 @@ enum Deprecation { deprecatedIn: '1.56.0', description: 'Passing invalid units to built-in functions.'), + duplicateVariableFlags('duplicate-var-flags', + deprecatedIn: '1.62.0', + description: + 'Using !default or !global multiple times for one variable.'), + /// Deprecation for `@import` rules. import.future('import', description: '@import rules.'), diff --git a/lib/src/parse/stylesheet.dart b/lib/src/parse/stylesheet.dart index 1ee59febe..0a4286687 100644 --- a/lib/src/parse/stylesheet.dart +++ b/lib/src/parse/stylesheet.dart @@ -230,11 +230,25 @@ abstract class StylesheetParser extends Parser { while (scanner.scanChar($exclamation)) { var flag = identifier(); if (flag == 'default') { + if (guarded) { + logger.warnForDeprecation( + Deprecation.duplicateVariableFlags, + '!default should only be written once for each variable.\n' + 'This will be an error in Dart Sass 2.0.0.', + span: scanner.spanFrom(flagStart)); + } + guarded = true; } else if (flag == 'global') { if (namespace != null) { error("!global isn't allowed for variables in other modules.", scanner.spanFrom(flagStart)); + } else if (global) { + logger.warnForDeprecation( + Deprecation.duplicateVariableFlags, + '!global should only be written once for each variable.\n' + 'This will be an error in Dart Sass 2.0.0.', + span: scanner.spanFrom(flagStart)); } global = true; diff --git a/pkg/sass_api/CHANGELOG.md b/pkg/sass_api/CHANGELOG.md index e251836b1..4241db909 100644 --- a/pkg/sass_api/CHANGELOG.md +++ b/pkg/sass_api/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.3.0 + +* No user-visible changes. + ## 6.2.0 * No user-visible changes. diff --git a/pkg/sass_api/pubspec.yaml b/pkg/sass_api/pubspec.yaml index a85600509..b6082240d 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: 6.2.0 +version: 6.3.0-dev description: Additional APIs for Dart Sass. homepage: https://github.com/sass/dart-sass @@ -10,7 +10,7 @@ environment: sdk: ">=2.17.0 <3.0.0" dependencies: - sass: 1.61.0 + sass: 1.62.0 dev_dependencies: dartdoc: ^5.0.0 diff --git a/pubspec.yaml b/pubspec.yaml index 1e967c589..6e7f0d71e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.61.0 +version: 1.62.0-dev description: A Sass implementation in Dart. homepage: https://github.com/sass/dart-sass