From 60af5f6c25c3226f21fe78ee63d4d14947371b8f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Jul 2019 13:31:13 -0700 Subject: [PATCH 01/23] Release 1.22.2 (#745) The CHANGELOG entry from #727 got misplaced; that code hasn't been released yet. --- CHANGELOG.md | 12 +++++++----- pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aae7fce..6ee2c0ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.22.2 + +### JavaScript API + +* Avoid re-assigning the `require()` function to make the code statically + analyzable by Webpack. + ## 1.22.1 ### JavaScript API @@ -27,11 +34,6 @@ * Add a top-level `warn()` function for custom functions and importers to print warning messages. -### JavaScript API - -* Avoid re-assigning the `require()` function to make the code statically - analyzable by Webpack. - ## 1.20.3 * No user-visible changes. diff --git a/pubspec.yaml b/pubspec.yaml index 690eaebb..7b9aaef0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.22.1 +version: 1.22.2 description: A Sass implementation in Dart. author: Dart Team homepage: https://github.com/sass/dart-sass From ed06a41afcd0c4f640624f313c3a1ea0e3be8f0d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 14:44:57 -0700 Subject: [PATCH 02/23] Fix the argument name for a single-argument saturate() function Closes #699 --- CHANGELOG.md | 6 ++++++ lib/src/functions/color.dart | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee2c0ce..69cfc82d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.22.3 + +* **Potentially breaking bug fix:** The argument name for the `saturate()` + function is now `$amount`, to match the name in LibSass and originally in Ruby + Sass. + ## 1.22.2 ### JavaScript API diff --git a/lib/src/functions/color.dart b/lib/src/functions/color.dart index 89f28bca..0fd4aab4 100644 --- a/lib/src/functions/color.dart +++ b/lib/src/functions/color.dart @@ -130,8 +130,8 @@ final global = UnmodifiableListView([ }), BuiltInCallable.overloaded("saturate", { - r"$number": (arguments) { - var number = arguments[0].assertNumber("number"); + r"$amount": (arguments) { + var number = arguments[0].assertNumber("amount"); return SassString("saturate(${number.toCssString()})", quotes: false); }, r"$color, $amount": (arguments) { From 9838caff6fd7ec10f72bc8cd898675e606640b6b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 15:13:36 -0700 Subject: [PATCH 03/23] Improve errors for alpha() with the wrong number of arguments Closes #700 --- CHANGELOG.md | 3 +++ lib/src/functions/color.dart | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69cfc82d..bbafa65e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ function is now `$amount`, to match the name in LibSass and originally in Ruby Sass. +* The `alpha()` function now produces clearer error messages when the wrong + number of arguments are passed. + ## 1.22.2 ### JavaScript API diff --git a/lib/src/functions/color.dart b/lib/src/functions/color.dart index 0fd4aab4..1109c23a 100644 --- a/lib/src/functions/color.dart +++ b/lib/src/functions/color.dart @@ -171,17 +171,23 @@ final global = UnmodifiableListView([ return SassNumber(color.alpha); }, r"$args...": (arguments) { - if (arguments[0].asList.every((argument) => - argument is SassString && - !argument.hasQuotes && - argument.text.contains(_microsoftFilterStart))) { + var argList = arguments[0].asList; + if (argList.isNotEmpty && + argList.every((argument) => + argument is SassString && + !argument.hasQuotes && + argument.text.contains(_microsoftFilterStart))) { // Suport the proprietary Microsoft alpha() function. return _functionString("alpha", arguments); } - assert(arguments.length != 1); - throw SassScriptException( - "Only 1 argument allowed, but ${arguments.length} were passed."); + assert(argList.length != 1); + if (argList.isEmpty) { + throw SassScriptException("Missing argument \$color."); + } else { + throw SassScriptException( + "Only 1 argument allowed, but ${argList.length} were passed."); + } } }), From d5adb4621e498191bc3dc39a7ad39b8f77975ec4 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 15:46:00 -0700 Subject: [PATCH 04/23] Fix invert() with $weight: 50% Closes #704 --- CHANGELOG.md | 5 +++++ lib/src/functions/color.dart | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbafa65e..5f6f3046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ function is now `$amount`, to match the name in LibSass and originally in Ruby Sass. +* **Potentially breaking bug fix:** The `invert()` function now properly returns + `#808080` when passed `$weight: 50%`. This matches the behavior in LibSass and + originally in Ruby Sass, as well as being consistent with other nearby values + of `$weight`. + * The `alpha()` function now produces clearer error messages when the wrong number of arguments are passed. diff --git a/lib/src/functions/color.dart b/lib/src/functions/color.dart index 1109c23a..52889738 100644 --- a/lib/src/functions/color.dart +++ b/lib/src/functions/color.dart @@ -47,7 +47,7 @@ final global = UnmodifiableListView([ } }), - BuiltInCallable("invert", r"$color, $weight: 50%", (arguments) { + BuiltInCallable("invert", r"$color, $weight: 100%", (arguments) { if (arguments[0] is SassNumber) { return _functionString("invert", arguments.take(1)); } @@ -56,7 +56,6 @@ final global = UnmodifiableListView([ var weight = arguments[1].assertNumber("weight"); var inverse = color.changeRgb( red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue); - if (weight.value == 50) return inverse; return _mixColors(inverse, color, weight); }), @@ -212,7 +211,7 @@ final module = BuiltInModule("color", [ // ### RGB _red, _green, _blue, _mix, - BuiltInCallable("invert", r"$color, $weight: 50%", (arguments) { + BuiltInCallable("invert", r"$color, $weight: 100%", (arguments) { if (arguments[0] is SassNumber) { var result = _functionString("invert", arguments.take(1)); warn("Passing a number to color.invert() is deprecated.\n" @@ -225,7 +224,6 @@ final module = BuiltInModule("color", [ var weight = arguments[1].assertNumber("weight"); var inverse = color.changeRgb( red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue); - if (weight.value == 50) return inverse; return _mixColors(inverse, color, weight); }), From 7bfba04b796a69755de53b8a95089e1a9fc22214 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 15:54:08 -0700 Subject: [PATCH 05/23] Throw an error for plain-CSS invert() with $weight Closes #705 --- CHANGELOG.md | 7 +++++++ lib/src/functions/color.dart | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f6f3046..60e01415 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ originally in Ruby Sass, as well as being consistent with other nearby values of `$weight`. +* **Potentially breaking bug fix:** The `invert()` function now throws an error + if it's used [as a plain CSS function][plain-CSS invert] *and* the Sass-only + `$weight` parameter is passed. This never did anything useful, so it's + considered a bug fix rather than a full breaking change. + + [plain-CSS invert]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/invert + * The `alpha()` function now produces clearer error messages when the wrong number of arguments are passed. diff --git a/lib/src/functions/color.dart b/lib/src/functions/color.dart index 52889738..7344a221 100644 --- a/lib/src/functions/color.dart +++ b/lib/src/functions/color.dart @@ -48,12 +48,17 @@ final global = UnmodifiableListView([ }), BuiltInCallable("invert", r"$color, $weight: 100%", (arguments) { + var weight = arguments[1].assertNumber("weight"); if (arguments[0] is SassNumber) { + if (weight.value != 100 || !weight.hasUnit("%")) { + throw "Only one argument may be passed to the plain-CSS invert() " + "function."; + } + return _functionString("invert", arguments.take(1)); } var color = arguments[0].assertColor("color"); - var weight = arguments[1].assertNumber("weight"); var inverse = color.changeRgb( red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue); @@ -212,7 +217,13 @@ final module = BuiltInModule("color", [ _red, _green, _blue, _mix, BuiltInCallable("invert", r"$color, $weight: 100%", (arguments) { + var weight = arguments[1].assertNumber("weight"); if (arguments[0] is SassNumber) { + if (weight.value != 100 || !weight.hasUnit("%")) { + throw "Only one argument may be passed to the plain-CSS invert() " + "function."; + } + var result = _functionString("invert", arguments.take(1)); warn("Passing a number to color.invert() is deprecated.\n" "\n" @@ -221,7 +232,6 @@ final module = BuiltInModule("color", [ } var color = arguments[0].assertColor("color"); - var weight = arguments[1].assertNumber("weight"); var inverse = color.changeRgb( red: 255 - color.red, green: 255 - color.green, blue: 255 - color.blue); From 2105a138c0b098f8bb34839d3a5f697a31ee2bac Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 16:03:44 -0700 Subject: [PATCH 06/23] Clamp $alpha in adjust-color() with HSL args Closes #708 --- CHANGELOG.md | 3 +++ lib/src/functions/color.dart | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e01415..55aee001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ [plain-CSS invert]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/invert +* The `adjust-color()` function no longer throws an error when a large `$alpha` + value is combined with HSL adjustments. + * The `alpha()` function now produces clearer error messages when the wrong number of arguments are passed. diff --git a/lib/src/functions/color.dart b/lib/src/functions/color.dart index 7344a221..e2063e79 100644 --- a/lib/src/functions/color.dart +++ b/lib/src/functions/color.dart @@ -414,7 +414,7 @@ final _adjust = BuiltInCallable("adjust", r"$color, $kwargs...", (arguments) { hue: color.hue + (hue ?? 0), saturation: (color.saturation + (saturation ?? 0)).clamp(0, 100), lightness: (color.lightness + (lightness ?? 0)).clamp(0, 100), - alpha: color.alpha + (alpha ?? 0)); + alpha: (color.alpha + (alpha ?? 0)).clamp(0, 1)); } else if (alpha != null) { return color.changeAlpha((color.alpha + (alpha ?? 0)).clamp(0, 1)); } else { From 40df8e3bc17f1c63bf070d846e7ef6cbbdd25ed0 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 16:30:59 -0700 Subject: [PATCH 07/23] Fix str-slice() with astral plane characters Closes #732 --- CHANGELOG.md | 4 ++++ lib/src/functions/string.dart | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55aee001..be52f673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ * The `alpha()` function now produces clearer error messages when the wrong number of arguments are passed. +* Fix a bug where the `str-slice()` function could produce invalid output when + passed a string that contains characters that aren't represented as a single + byte in UTF-16. + ## 1.22.2 ### JavaScript API diff --git a/lib/src/functions/string.dart b/lib/src/functions/string.dart index a51254e3..6c214c96 100644 --- a/lib/src/functions/string.dart +++ b/lib/src/functions/string.dart @@ -113,7 +113,7 @@ final _slice = return SassString( string.text.substring( codepointIndexToCodeUnitIndex(string.text, startCodepoint), - codepointIndexToCodeUnitIndex(string.text, endCodepoint) + 1), + codepointIndexToCodeUnitIndex(string.text, endCodepoint + 1)), quotes: string.hasQuotes); }); From 821b5e2521d31aea1825d51c2b2377d01c66803c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 16:42:19 -0700 Subject: [PATCH 08/23] Fix str-insert() with $index: -1 Closes #733 --- CHANGELOG.md | 4 ++++ lib/src/functions/string.dart | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be52f673..786a3653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ [plain-CSS invert]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/invert +* **Potentially breaking bug fix**: The `str-insert()` function now properly + inserts at the end of the string if the `$index` is `-1`. This matches the + behavior in LibSass and originally in Ruby Sass. + * The `adjust-color()` function no longer throws an error when a large `$alpha` value is combined with HSL adjustments. diff --git a/lib/src/functions/string.dart b/lib/src/functions/string.dart index 6c214c96..4eb663a7 100644 --- a/lib/src/functions/string.dart +++ b/lib/src/functions/string.dart @@ -64,10 +64,13 @@ final _insert = // the `$insert` string is at `$index` in the result, which means that we // want to insert before `$index` if it's positive and after if it's // negative. - if (indexInt < 0) indexInt++; + if (indexInt < 0) { + // +1 because negative indexes start counting from -1 rather than 0, and + // another +1 because we want to insert *after* that index. + indexInt = string.sassLength + indexInt + 2; + } var codepointIndex = _codepointForIndex(indexInt, string.sassLength); - var codeUnitIndex = codepointIndexToCodeUnitIndex(string.text, codepointIndex); return SassString( From 47e0cfc8c8701916367019dad5f67818186190cb Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 17:16:46 -0700 Subject: [PATCH 09/23] Empty maps have undecided separators Closes #737 --- CHANGELOG.md | 5 +++++ lib/src/value/map.dart | 3 ++- test/dart_api/value/map_test.dart | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 786a3653..31732c3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,11 @@ inserts at the end of the string if the `$index` is `-1`. This matches the behavior in LibSass and originally in Ruby Sass. +* **Potentially breaking bug fix**: An empty map returned by `map-remove()` is + now treated as identical to the literal value `()`, rather than being treated + as though it had a comma separator. This matches the original behavior in Ruby + Sass. + * The `adjust-color()` function no longer throws an error when a large `$alpha` value is combined with HSL adjustments. diff --git a/lib/src/value/map.dart b/lib/src/value/map.dart index f33128af..22d26c13 100644 --- a/lib/src/value/map.dart +++ b/lib/src/value/map.dart @@ -10,7 +10,8 @@ import 'external/value.dart' as ext; class SassMap extends Value implements ext.SassMap { final Map contents; - ListSeparator get separator => ListSeparator.comma; + ListSeparator get separator => + contents.isEmpty ? ListSeparator.undecided : ListSeparator.comma; List get asList { var result = []; diff --git a/test/dart_api/value/map_test.dart b/test/dart_api/value/map_test.dart index d6391674..71fe0e78 100644 --- a/test/dart_api/value/map_test.dart +++ b/test/dart_api/value/map_test.dart @@ -15,7 +15,7 @@ main() { SassMap value; setUp(() => value = parseValue("(a: b, c: d)") as SassMap); - test("is comma-separated", () { + test("has an undecided separator", () { expect(value.separator, equals(ListSeparator.comma)); }); @@ -143,8 +143,8 @@ main() { SassMap value; setUp(() => value = parseValue("map-remove((a: b), a)") as SassMap); - test("is comma-separated", () { - expect(value.separator, equals(ListSeparator.comma)); + test("has an undecided separator", () { + expect(value.separator, equals(ListSeparator.undecided)); }); test("returns its contents as a map", () { From 5ff434da6a1ebda73f0a91e4bd0ebebc01c50ed9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 17:21:05 -0700 Subject: [PATCH 10/23] Fix join() and append() $separator error messages Closes #738 --- CHANGELOG.md | 3 +++ lib/src/functions/list.dart | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31732c3d..e022a81e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,9 @@ passed a string that contains characters that aren't represented as a single byte in UTF-16. +* Improve the error message for an unknown separator name passed to the `join()` + or `append()` functions. + ## 1.22.2 ### JavaScript API diff --git a/lib/src/functions/list.dart b/lib/src/functions/list.dart index abe4871e..c683f972 100644 --- a/lib/src/functions/list.dart +++ b/lib/src/functions/list.dart @@ -63,7 +63,7 @@ final _join = BuiltInCallable( separator = ListSeparator.comma; } else { throw SassScriptException( - '\$$separator: Must be "space", "comma", or "auto".'); + '\$separator: Must be "space", "comma", or "auto".'); } var bracketed = bracketedParam is SassString && bracketedParam.text == 'auto' @@ -91,7 +91,7 @@ final _append = separator = ListSeparator.comma; } else { throw SassScriptException( - '\$$separator: Must be "space", "comma", or "auto".'); + '\$separator: Must be "space", "comma", or "auto".'); } var newList = [...list.asList, value]; From eff8c37457d786bf77987390fe48b0191e9b06bf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 17:24:49 -0700 Subject: [PATCH 11/23] Fix a deadlock in zip() Closes #739 --- CHANGELOG.md | 2 ++ lib/src/functions/list.dart | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e022a81e..43654dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ * Improve the error message for an unknown separator name passed to the `join()` or `append()` functions. +* The `zip()` function no longer deadlocks if passed no arguments. + ## 1.22.2 ### JavaScript API diff --git a/lib/src/functions/list.dart b/lib/src/functions/list.dart index c683f972..f8db2138 100644 --- a/lib/src/functions/list.dart +++ b/lib/src/functions/list.dart @@ -100,6 +100,10 @@ final _append = final _zip = BuiltInCallable("zip", r"$lists...", (arguments) { var lists = arguments[0].asList.map((list) => list.asList).toList(); + if (lists.isEmpty) { + return const SassList.empty(separator: ListSeparator.comma); + } + var i = 0; var results = []; while (lists.every((list) => i != list.length)) { From d3e288ccf2cbc8d6dd0ba3182158d64d1c6cfb0f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 17:30:55 -0700 Subject: [PATCH 12/23] Support map-remove() with a named $key argument Closes #742 --- CHANGELOG.md | 3 +++ lib/src/functions/map.dart | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43654dd9..980a268e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,9 @@ * The `zip()` function no longer deadlocks if passed no arguments. +* The `map-remove()` function can now take a `$key` named argument. This matches + the signature in LibSass and originally in Ruby Sass. + ## 1.22.2 ### JavaScript API diff --git a/lib/src/functions/map.dart b/lib/src/functions/map.dart index 7ef02474..c71f3726 100644 --- a/lib/src/functions/map.dart +++ b/lib/src/functions/map.dart @@ -36,14 +36,23 @@ final _merge = BuiltInCallable("merge", r"$map1, $map2", (arguments) { return SassMap({...map1.contents, ...map2.contents}); }); -final _remove = BuiltInCallable("remove", r"$map, $keys...", (arguments) { - var map = arguments[0].assertMap("map"); - var keys = arguments[1]; - var mutableMap = Map.of(map.contents); - for (var key in keys.asList) { - mutableMap.remove(key); +final _remove = BuiltInCallable.overloaded("remove", { + // Because the signature below has an explicit `$key` argument, it doesn't + // allow zero keys to be passed. We want to allow that case, so we add an + // explicit overload for it. + r"$map": (arguments) => arguments[0].assertMap("map"), + + // The first argument has special handling so that the $key parameter can be + // passed by name. + r"$map, $key, $keys...": (arguments) { + var map = arguments[0].assertMap("map"); + var keys = [arguments[1], ...arguments[2].asList]; + var mutableMap = Map.of(map.contents); + for (var key in keys) { + mutableMap.remove(key); + } + return SassMap(mutableMap); } - return SassMap(mutableMap); }); final _keys = BuiltInCallable( From faa053733ab70486c2da3b8dc52f92b44988ca88 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 2 Jul 2019 17:39:10 -0700 Subject: [PATCH 13/23] Release 1.22.3 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 7b9aaef0..f43f3fc5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.22.2 +version: 1.22.3 description: A Sass implementation in Dart. author: Dart Team homepage: https://github.com/sass/dart-sass From b7999e41ad9e47e559d9fc4dc3104eda79f658f1 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 3 Jul 2019 16:56:33 -0700 Subject: [PATCH 14/23] Fix a new lint (#752) --- lib/src/io/vm.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/io/vm.dart b/lib/src/io/vm.dart index c1399167..aa5eaf06 100644 --- a/lib/src/io/vm.dart +++ b/lib/src/io/vm.dart @@ -74,7 +74,7 @@ void ensureDir(String path) => io.Directory(path).createSync(recursive: true); Iterable listDir(String path, {bool recursive = false}) => io.Directory(path) .listSync(recursive: recursive) - .where((entity) => entity is io.File) + .whereType() .map((entity) => entity.path); DateTime modificationTime(String path) { From fb75fc39ce6d6e75be14588ee6fe78790c8dd05a Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Jul 2019 16:02:40 -0700 Subject: [PATCH 15/23] Fix a Travis task that was broken by sass/sass-spec#1426 (#757) --- tool/travis/task/specs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/travis/task/specs.sh b/tool/travis/task/specs.sh index c30c14d2..565048e7 100755 --- a/tool/travis/task/specs.sh +++ b/tool/travis/task/specs.sh @@ -4,5 +4,5 @@ # https://opensource.org/licenses/MIT. echo "$(tput bold)Running sass-spec against $(dart --version &> /dev/stdout).$(tput sgr0)" -if [ "$ASYNC" = true ]; then extra_args="--dart-args --async"; fi +if [ "$ASYNC" = true ]; then extra_args="--cmd-args --async"; fi (cd sass-spec; bundle exec sass-spec.rb --dart .. $extra_args) From a7172a2b1dd48b339e5d57159ed364ffb9f5812e Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 01:53:36 +0100 Subject: [PATCH 16/23] Update benchmarks (#759) --- perf.md | 145 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/perf.md b/perf.md index d0ec2819..4986a35d 100644 --- a/perf.md +++ b/perf.md @@ -3,8 +3,8 @@ the benefit Dart Sass could provide relative to other implementations. This was tested against: -* libsass 8d220b74 and sassc 3f84e23 compiled with g++ (Debian 7.3.0-18) 7.3.0. -* Dart Sass 2868ab3 on Dart 2.3.0 and Node v11.14.0. +* libsass 0f3d6ad1 and sassc 4674821 compiled with g++ (Debian 7.3.0-18) 7.3.0. +* Dart Sass 088fc28 on Dart 2.4.0 and Node v12.0.0. * Ruby Sass 8d1edc76 on ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]. on Debian x64 with Intel Xeon E5-1650 v3 @ 3.50GHz. The Dart Sass @@ -21,147 +21,148 @@ I ran five instances of each configuration and recorded the fastest time. Running on a file containing 4 instances of `.foo {a: b}`: * sassc: 0.004s -* Dart Sass from a script snapshot: 0.188s -* Dart Sass native executable: 0.014s -* Dart Sass on Node.js: 0.169s -* Ruby Sass with a hot cache: 0.151s +* Dart Sass from a script snapshot: 0.219s +* Dart Sass native executable: 0.020s +* Dart Sass on Node.js: 0.200s +* Ruby Sass with a hot cache: 0.155s Based on these numbers, Dart Sass from a native executable is approximately: -* 3.5x slower than libsass -* 12.1x faster than Dart Sass on Node -* 10.8x faster than Ruby Sass +* 5.0x slower than libsass +* 10.0x faster than Dart Sass on Node +* 7.8x faster than Ruby Sass ## Large Plain CSS Running on a file containing 2^17 instances of `.foo {a: b}`: -* sassc: 1.909s -* Dart Sass from a script snapshot: 1.586s -* Dart Sass native executable: 1.438s -* Dart Sass on Node.js: 3.028s -* Ruby Sass with a hot cache: 10.772s +* sassc: 1.714s +* Dart Sass from a script snapshot: 1.606s +* Dart Sass native executable: 1.547s +* Dart Sass on Node.js: 2.672s +* Ruby Sass with a hot cache: 11.145s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.3x faster than libsass -* 2.1x faster than Dart Sass on Node -* 7.5x faster than Ruby Sass +* 1.1x faster than libsass +* 1.7x faster than Dart Sass on Node +* 7.2x faster than Ruby Sass ## Preceding Sparse `@extend` Running on a file containing `.x {@extend .y}`, 2^17 instances of `.foo {a: b}`, and then `.y {a: b}`: -* sassc: 2.007s -* Dart Sass from a script snapshot: 1.617s -* Dart Sass native executable: 1.457s -* Dart Sass on Node.js: 3.072s -* Ruby Sass with a hot cache: 16.456s +* sassc: 1.750s +* Dart Sass from a script snapshot: 1.602s +* Dart Sass native executable: 1.585s +* Dart Sass on Node.js: 2.782s +* Ruby Sass with a hot cache: 17.012s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.4x faster than libsass -* 2.1x faster than Dart Sass on Node -* 11.3x faster than Ruby Sass +* 1.1x faster than libsass +* 1.8x faster than Dart Sass on Node +* 10.7x faster than Ruby Sass ## Following Sparse `@extend` Running on a file containing `.y {a: b}`, 2^17 instances of `.foo {a: b}`, and then `.x {@extend .y}`: -* sassc: 1.934s -* Dart Sass from a script snapshot: 1.594s -* Dart Sass native executable: 1.433s -* Dart Sass on Node.js: 3.099s -* Ruby Sass with a hot cache: 16.497s +* sassc: 1.724s +* Dart Sass from a script snapshot: 1.610s +* Dart Sass native executable: 1.568s +* Dart Sass on Node.js: 2.712s +* Ruby Sass with a hot cache: 16.670s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.3x faster than libsass -* 2.2x faster than Dart Sass on Node -* 11.5x faster than Ruby Sass +* 1.1x faster than libsass +* 1.7x faster than Dart Sass on Node +* 10.6x faster than Ruby Sass ## Preceding Dense `@extend` Running on a file containing `.bar {@extend .foo}` followed by 2^17 instances of `.foo {a: b}`: -* sassc: 2.033s -* Dart Sass from a script snapshot: 2.380s -* Dart Sass native executable: 2.398s -* Dart Sass on Node.js: 6.523s -* Ruby Sass with a hot cache: 29.717s +* sassc: 2.290s +* Dart Sass from a script snapshot: 2.476s +* Dart Sass native executable: 2.566s +* Dart Sass on Node.js: 5.399s +* Ruby Sass with a hot cache: 29.002s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.2x slower than libsass -* 2.7x faster than Dart Sass on Node -* 12.4x faster than Ruby Sass +* 1.1x slower than libsass +* 2.1x faster than Dart Sass on Node +* 11.3x faster than Ruby Sass ## Following Dense `@extend` Running on a file containing 2^17 instances of `.foo {a: b}` followed by `.bar {@extend .foo}`: -* sassc: 2.065s -* Dart Sass from a script snapshot: 2.312s -* Dart Sass native executable: 2.256s -* Dart Sass on Node.js: 6.760s -* Ruby Sass with a hot cache: 28.755s +* sassc: 2.317s +* Dart Sass from a script snapshot: 2.381s +* Dart Sass native executable: 2.461s +* Dart Sass on Node.js: 5.481s +* Ruby Sass with a hot cache: 29.197s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x slower than libsass -* 3.0x faster than Dart Sass on Node -* 12.7x faster than Ruby Sass +* 2.2x faster than Dart Sass on Node +* 11.9x faster than Ruby Sass ## Bootstrap Running on a file containing 16 instances of importing the Bootstrap framework: -* sassc: 0.898s -* Dart Sass from a script snapshot: 1.550s -* Dart Sass native executable: 0.907s -* Dart Sass on Node.js: 3.559s -* Ruby Sass with a hot cache: 12.649s +* sassc: 0.763s +* Dart Sass from a script snapshot: 1.613s +* Dart Sass native executable: 0.992s +* Dart Sass on Node.js: 3.529s +* Ruby Sass with a hot cache: 12.969s Based on these numbers, Dart Sass from a native executable is approximately: -* identical to libsass -* 3.9x faster than Dart Sass on Node -* 13.9x faster than Ruby Sass +* 1.3x slower than libsass +* 3.6x faster than Dart Sass on Node +* 13.1x faster than Ruby Sass ## a11ycolor Running on a file containing test cases for a computation-intensive color-processing library: -* sassc: 0.332s -* Dart Sass from a script snapshot: 0.726s -* Dart Sass native executable: 0.564s -* Dart Sass on Node.js: 2.027s -* Ruby Sass with a hot cache: 5.020s +* sassc: 0.262s +* Dart Sass from a script snapshot: 0.805s +* Dart Sass native executable: 0.612s +* Dart Sass on Node.js: 1.876s +* Ruby Sass with a hot cache: 5.396s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.7x slower than libsass -* 3.6x faster than Dart Sass on Node -* 8.9x faster than Ruby Sass +* 2.3x slower than libsass +* 3.1x faster than Dart Sass on Node +* 8.8x faster than Ruby Sass ## Susy Running on a file containing test cases for the computation-intensive Susy grid framework: -* sassc: 0.290s -* Dart Sass from a script snapshot: 0.649s -* Dart Sass native executable: 0.225s -* Dart Sass on Node.js: 1.293s -* Ruby Sass with a hot cache: 1.506s +* sassc: 0.244s +* Dart Sass from a script snapshot: 0.673s +* Dart Sass native executable: 0.248s +* Dart Sass on Node.js: 1.361s +* Ruby Sass with a hot cache: 1.576s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.3x faster than libsass -* 5.7x faster than Dart Sass on Node -* 6.7x faster than Ruby Sass +* identical to libsass +* 5.5x faster than Dart Sass on Node +* 6.4x faster than Ruby Sass # Prior Measurements +* [1.20.2](https://github.com/sass/dart-sass/blob/4b7699291c9f69533d25980d23b0647266b665f2/perf.md). * [1.13.4](https://github.com/sass/dart-sass/blob/b6ccc91a138e75420227ff79381c5f70e60254f1/perf.md). * [1.6.0](https://github.com/sass/dart-sass/blob/048cbe197a77e1cf4b837a40a5acb737e949fd5c/perf.md). * [1.0.0-alpha.8](https://github.com/sass/dart-sass/blob/be44245a849f2bb18b5ca1fc74f3043a36da17f0/perf.md). From 0e47e03305c25fdfc2175891c4fa16a407fcaa08 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 01:55:30 +0100 Subject: [PATCH 17/23] Fix at-rules in nested imports (#758) Closes #755 --- CHANGELOG.md | 5 +++++ lib/src/visitor/async_evaluate.dart | 5 ++++- lib/src/visitor/evaluate.dart | 7 +++++-- pubspec.yaml | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 980a268e..855c0c91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.22.4 + +* Fix a bug where at-rules imported from within a style rule would appear within + that style rule rather than at the root of the document. + ## 1.22.3 * **Potentially breaking bug fix:** The argument name for the `saturate()` diff --git a/lib/src/visitor/async_evaluate.dart b/lib/src/visitor/async_evaluate.dart index ed4810f9..40e111e4 100644 --- a/lib/src/visitor/async_evaluate.dart +++ b/lib/src/visitor/async_evaluate.dart @@ -2625,7 +2625,10 @@ class _ImportedCssVisitor implements ModifiableCssVisitor { _ImportedCssVisitor(this._visitor); - void visitCssAtRule(ModifiableCssAtRule node) => _visitor._addChild(node); + void visitCssAtRule(ModifiableCssAtRule node) { + _visitor._addChild(node, + through: node.isChildless ? null : (node) => node is CssStyleRule); + } void visitCssComment(ModifiableCssComment node) => _visitor._addChild(node); diff --git a/lib/src/visitor/evaluate.dart b/lib/src/visitor/evaluate.dart index 626b073a..fcd07f9a 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: 7915d98d80d1288aa327578a9d274d02c814528a +// Checksum: cae91fd0fcd94fbb45712286a85761d69fef5415 // // ignore_for_file: unused_import @@ -2590,7 +2590,10 @@ class _ImportedCssVisitor implements ModifiableCssVisitor { _ImportedCssVisitor(this._visitor); - void visitCssAtRule(ModifiableCssAtRule node) => _visitor._addChild(node); + void visitCssAtRule(ModifiableCssAtRule node) { + _visitor._addChild(node, + through: node.isChildless ? null : (node) => node is CssStyleRule); + } void visitCssComment(ModifiableCssComment node) => _visitor._addChild(node); diff --git a/pubspec.yaml b/pubspec.yaml index f43f3fc5..0d52a7fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.22.3 +version: 1.22.4 description: A Sass implementation in Dart. author: Dart Team homepage: https://github.com/sass/dart-sass From a8418827249eaed56fe6bb4bc0fb9dffa2a09656 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 13:12:31 -0700 Subject: [PATCH 18/23] Don't compile to JS in minified mode The JS size doesn't really matter on the server side, and this makes profiling the release-mode binary substantially easier, as well as improving the quality of stack traces provided by downstream users. --- tool/grind/npm.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tool/grind/npm.dart b/tool/grind/npm.dart index 1b77d9cc..8ab71e44 100644 --- a/tool/grind/npm.dart +++ b/tool/grind/npm.dart @@ -40,7 +40,10 @@ void _js({@required bool release}) { // * We expect our test coverage to ensure that nothing throws subtypes of // Error. // * We thoroughly test edge cases in user input. - if (release) ...["-O4", "--fast-startup"] + // + // We don't minify because download size isn't especially important + // server-side and it's nice to get readable stack traces from bug reports. + if (release) ...["-O4", "--no-minify", "--fast-startup"] ]); var text = destination .readAsStringSync() From a8e99e915279ac268f4c9ff2be42da4526be3e86 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 13:14:28 -0700 Subject: [PATCH 19/23] Pass a dummy isValidKey callback to normalized map and set The default implementation runs a type check, which was a performance bottleneck when compiled to JS. There's no need for this type check in practice, since we never pass a non-String value to the contains(), containsKey(), or remove() methods (and if we do, it will throw a TypeError in our tests). --- lib/src/utils.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/src/utils.dart b/lib/src/utils.dart index aecde2f6..5bf5e60a 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -306,7 +306,11 @@ bool startsWithIgnoreSeparator(String string, String prefix) { /// If [source] is passed, copies it into the map. Map normalizedMap([Map source]) { var map = LinkedHashMap( - equals: equalsIgnoreSeparator, hashCode: hashCodeIgnoreSeparator); + // Explicitly set this because the default implementation involves a type + // check, which is very expensive in dart2js. + isValidKey: (_) => true, + equals: equalsIgnoreSeparator, + hashCode: hashCodeIgnoreSeparator); if (source != null) map.addAll(source); return map; } @@ -316,7 +320,11 @@ Map normalizedMap([Map source]) { /// If [source] is passed, copies it into the set. Set normalizedSet([Iterable source]) { var set = LinkedHashSet( - equals: equalsIgnoreSeparator, hashCode: hashCodeIgnoreSeparator); + // Explicitly set this because the default implementation involves a type + // check, which is very expensive in dart2js. + isValidKey: (_) => true, + equals: equalsIgnoreSeparator, + hashCode: hashCodeIgnoreSeparator); if (source != null) set.addAll(source); return set; } From 58e9e74b37f95cb8924eec19cd9106c1dfb28f75 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 13:22:23 -0700 Subject: [PATCH 20/23] Use list comprehensions in *Evaluate._evaluateArguments As well as being arguably more readable, the toList() method was running a type check that was showing up as a minor bottleneck in JS profiles. --- lib/src/visitor/async_evaluate.dart | 14 +++++++++----- lib/src/visitor/evaluate.dart | 16 ++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/src/visitor/async_evaluate.dart b/lib/src/visitor/async_evaluate.dart index 40e111e4..ff1b6320 100644 --- a/lib/src/visitor/async_evaluate.dart +++ b/lib/src/visitor/async_evaluate.dart @@ -1962,15 +1962,19 @@ class _EvaluateVisitor {bool trackSpans}) async { trackSpans ??= _sourceMap; - var positional = (await mapAsync(arguments.positional, - (Expression expression) => expression.accept(this))) - .toList(); + var positional = [ + for (var expression in arguments.positional) await expression.accept(this) + ]; var named = await normalizedMapMapAsync( arguments.named, value: (_, expression) => expression.accept(this)); - var positionalNodes = - trackSpans ? arguments.positional.map(_expressionNode).toList() : null; + var positionalNodes = trackSpans + ? [ + for (var expression in arguments.positional) + _expressionNode(expression) + ] + : null; var namedNodes = trackSpans ? mapMap(arguments.named, value: (_, expression) => _expressionNode(expression)) diff --git a/lib/src/visitor/evaluate.dart b/lib/src/visitor/evaluate.dart index fcd07f9a..7e142053 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: cae91fd0fcd94fbb45712286a85761d69fef5415 +// Checksum: 1685f0e62002cbb13d3d54ea3d5166c4c7f8f678 // // ignore_for_file: unused_import @@ -1949,14 +1949,18 @@ class _EvaluateVisitor {bool trackSpans}) { trackSpans ??= _sourceMap; - var positional = arguments.positional - .map((Expression expression) => expression.accept(this)) - .toList(); + var positional = [ + for (var expression in arguments.positional) expression.accept(this) + ]; var named = normalizedMapMap(arguments.named, value: (_, expression) => expression.accept(this)); - var positionalNodes = - trackSpans ? arguments.positional.map(_expressionNode).toList() : null; + var positionalNodes = trackSpans + ? [ + for (var expression in arguments.positional) + _expressionNode(expression) + ] + : null; var namedNodes = trackSpans ? mapMap(arguments.named, value: (_, expression) => _expressionNode(expression)) From ed73c2c053435703cfbee8709f0dfb110cd31487 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 13:23:24 -0700 Subject: [PATCH 21/23] Update benchmarks for JS performance improvements As expected, this substantially improves the JS performance in logic-heavy benchmarks. I believe the other changes are just noise. --- perf.md | 155 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/perf.md b/perf.md index 4986a35d..96f7f703 100644 --- a/perf.md +++ b/perf.md @@ -4,7 +4,7 @@ the benefit Dart Sass could provide relative to other implementations. This was tested against: * libsass 0f3d6ad1 and sassc 4674821 compiled with g++ (Debian 7.3.0-18) 7.3.0. -* Dart Sass 088fc28 on Dart 2.4.0 and Node v12.0.0. +* Dart Sass 50a45a7 on Dart 2.4.0 and Node v12.0.0. * Ruby Sass 8d1edc76 on ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]. on Debian x64 with Intel Xeon E5-1650 v3 @ 3.50GHz. The Dart Sass @@ -20,43 +20,59 @@ I ran five instances of each configuration and recorded the fastest time. Running on a file containing 4 instances of `.foo {a: b}`: -* sassc: 0.004s -* Dart Sass from a script snapshot: 0.219s -* Dart Sass native executable: 0.020s -* Dart Sass on Node.js: 0.200s -* Ruby Sass with a hot cache: 0.155s +* sassc: 0.005s +* Dart Sass from a script snapshot: 0.216s +* Dart Sass native executable: 0.018s +* Dart Sass on Node.js: 0.209s +* Ruby Sass with a hot cache: 0.148s Based on these numbers, Dart Sass from a native executable is approximately: -* 5.0x slower than libsass -* 10.0x faster than Dart Sass on Node -* 7.8x faster than Ruby Sass +* 3.6x slower than libsass +* 11.6x faster than Dart Sass on Node +* 8.2x faster than Ruby Sass ## Large Plain CSS Running on a file containing 2^17 instances of `.foo {a: b}`: -* sassc: 1.714s -* Dart Sass from a script snapshot: 1.606s -* Dart Sass native executable: 1.547s -* Dart Sass on Node.js: 2.672s -* Ruby Sass with a hot cache: 11.145s +* sassc: 1.705s +* Dart Sass from a script snapshot: 1.550s +* Dart Sass native executable: 1.518s +* Dart Sass on Node.js: 2.765s +* Ruby Sass with a hot cache: 10.965s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x faster than libsass -* 1.7x faster than Dart Sass on Node +* 1.8x faster than Dart Sass on Node * 7.2x faster than Ruby Sass ## Preceding Sparse `@extend` Running on a file containing `.x {@extend .y}`, 2^17 instances of `.foo {a: b}`, and then `.y {a: b}`: -* sassc: 1.750s -* Dart Sass from a script snapshot: 1.602s -* Dart Sass native executable: 1.585s -* Dart Sass on Node.js: 2.782s -* Ruby Sass with a hot cache: 17.012s +* sassc: 1.712s +* Dart Sass from a script snapshot: 1.613s +* Dart Sass native executable: 1.582s +* Dart Sass on Node.js: 2.739s +* Ruby Sass with a hot cache: 16.472s + +Based on these numbers, Dart Sass from a native executable is approximately: + +* 1.1x faster than libsass +* 1.7x faster than Dart Sass on Node +* 10.4x faster than Ruby Sass + +## Following Sparse `@extend` + +Running on a file containing `.y {a: b}`, 2^17 instances of `.foo {a: b}`, and then `.x {@extend .y}`: + +* sassc: 1.701s +* Dart Sass from a script snapshot: 1.568s +* Dart Sass native executable: 1.543s +* Dart Sass on Node.js: 2.821s +* Ruby Sass with a hot cache: 16.469s Based on these numbers, Dart Sass from a native executable is approximately: @@ -64,104 +80,89 @@ Based on these numbers, Dart Sass from a native executable is approximately: * 1.8x faster than Dart Sass on Node * 10.7x faster than Ruby Sass -## Following Sparse `@extend` - -Running on a file containing `.y {a: b}`, 2^17 instances of `.foo {a: b}`, and then `.x {@extend .y}`: - -* sassc: 1.724s -* Dart Sass from a script snapshot: 1.610s -* Dart Sass native executable: 1.568s -* Dart Sass on Node.js: 2.712s -* Ruby Sass with a hot cache: 16.670s - -Based on these numbers, Dart Sass from a native executable is approximately: - -* 1.1x faster than libsass -* 1.7x faster than Dart Sass on Node -* 10.6x faster than Ruby Sass - ## Preceding Dense `@extend` Running on a file containing `.bar {@extend .foo}` followed by 2^17 instances of `.foo {a: b}`: -* sassc: 2.290s -* Dart Sass from a script snapshot: 2.476s -* Dart Sass native executable: 2.566s -* Dart Sass on Node.js: 5.399s -* Ruby Sass with a hot cache: 29.002s - -Based on these numbers, Dart Sass from a native executable is approximately: - -* 1.1x slower than libsass -* 2.1x faster than Dart Sass on Node -* 11.3x faster than Ruby Sass - -## Following Dense `@extend` - -Running on a file containing 2^17 instances of `.foo {a: b}` followed by `.bar {@extend .foo}`: - -* sassc: 2.317s -* Dart Sass from a script snapshot: 2.381s -* Dart Sass native executable: 2.461s -* Dart Sass on Node.js: 5.481s -* Ruby Sass with a hot cache: 29.197s +* sassc: 2.260s +* Dart Sass from a script snapshot: 2.405s +* Dart Sass native executable: 2.526s +* Dart Sass on Node.js: 5.612s +* Ruby Sass with a hot cache: 28.690s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x slower than libsass * 2.2x faster than Dart Sass on Node -* 11.9x faster than Ruby Sass +* 11.4x faster than Ruby Sass + +## Following Dense `@extend` + +Running on a file containing 2^17 instances of `.foo {a: b}` followed by `.bar {@extend .foo}`: + +* sassc: 2.289s +* Dart Sass from a script snapshot: 2.396s +* Dart Sass native executable: 2.457s +* Dart Sass on Node.js: 6.319s +* Ruby Sass with a hot cache: 28.708s + +Based on these numbers, Dart Sass from a native executable is approximately: + +* 1.1x slower than libsass +* 2.6x faster than Dart Sass on Node +* 11.7x faster than Ruby Sass ## Bootstrap Running on a file containing 16 instances of importing the Bootstrap framework: -* sassc: 0.763s -* Dart Sass from a script snapshot: 1.613s -* Dart Sass native executable: 0.992s -* Dart Sass on Node.js: 3.529s -* Ruby Sass with a hot cache: 12.969s +* sassc: 0.767s +* Dart Sass from a script snapshot: 1.534s +* Dart Sass native executable: 0.955s +* Dart Sass on Node.js: 3.156s +* Ruby Sass with a hot cache: 12.521s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.3x slower than libsass -* 3.6x faster than Dart Sass on Node +* 1.2x slower than libsass +* 3.3x faster than Dart Sass on Node * 13.1x faster than Ruby Sass ## a11ycolor Running on a file containing test cases for a computation-intensive color-processing library: -* sassc: 0.262s -* Dart Sass from a script snapshot: 0.805s -* Dart Sass native executable: 0.612s -* Dart Sass on Node.js: 1.876s -* Ruby Sass with a hot cache: 5.396s +* sassc: 0.248s +* Dart Sass from a script snapshot: 0.736s +* Dart Sass native executable: 0.565s +* Dart Sass on Node.js: 1.043s +* Ruby Sass with a hot cache: 5.091s Based on these numbers, Dart Sass from a native executable is approximately: * 2.3x slower than libsass -* 3.1x faster than Dart Sass on Node -* 8.8x faster than Ruby Sass +* 1.8x faster than Dart Sass on Node +* 9.0x faster than Ruby Sass ## Susy Running on a file containing test cases for the computation-intensive Susy grid framework: -* sassc: 0.244s +* sassc: 0.248s * Dart Sass from a script snapshot: 0.673s -* Dart Sass native executable: 0.248s -* Dart Sass on Node.js: 1.361s -* Ruby Sass with a hot cache: 1.576s +* Dart Sass native executable: 0.237s +* Dart Sass on Node.js: 0.990s +* Ruby Sass with a hot cache: 1.527s Based on these numbers, Dart Sass from a native executable is approximately: * identical to libsass -* 5.5x faster than Dart Sass on Node +* 4.2x faster than Dart Sass on Node * 6.4x faster than Ruby Sass # Prior Measurements +* [1.22.4](https://github.com/sass/dart-sass/blob/a7172a2b1dd48b339e5d57159ed364ffb9f5812e/perf.md). * [1.20.2](https://github.com/sass/dart-sass/blob/4b7699291c9f69533d25980d23b0647266b665f2/perf.md). * [1.13.4](https://github.com/sass/dart-sass/blob/b6ccc91a138e75420227ff79381c5f70e60254f1/perf.md). * [1.6.0](https://github.com/sass/dart-sass/blob/048cbe197a77e1cf4b837a40a5acb737e949fd5c/perf.md). From 535030bb0faaa1b1076f014afcbc11a19b9a5e21 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jul 2019 13:25:40 -0700 Subject: [PATCH 22/23] Release 1.22.5 --- CHANGELOG.md | 6 ++++++ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 855c0c91..4f9a7485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.22.5 + +### JavaScript API + +* Improve performance for logic-heavy stylesheets. + ## 1.22.4 * Fix a bug where at-rules imported from within a style rule would appear within diff --git a/pubspec.yaml b/pubspec.yaml index 0d52a7fa..a4b51b53 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.22.4 +version: 1.22.5 description: A Sass implementation in Dart. author: Dart Team homepage: https://github.com/sass/dart-sass From d91e758889ee11af43406e884f5d7f3ad0bfc560 Mon Sep 17 00:00:00 2001 From: Marcel Greter Date: Tue, 16 Jul 2019 01:44:32 +0200 Subject: [PATCH 23/23] Fix typo in silent comment error message (#761) --- lib/src/parse/scss.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/parse/scss.dart b/lib/src/parse/scss.dart index 37cbd7fe..43903328 100644 --- a/lib/src/parse/scss.dart +++ b/lib/src/parse/scss.dart @@ -153,7 +153,7 @@ class ScssParser extends StylesheetParser { } while (scanner.scan("//")); if (plainCss) { - error("Silent comments arne't allowed in plain CSS.", + error("Silent comments aren't allowed in plain CSS.", scanner.spanFrom(start)); }