mirror of
https://github.com/danog/dart-sass.git
synced 2024-12-12 09:09:39 +01:00
Merge pull request #765 from sass/merge-master
Merge origin/master into feature.use
This commit is contained in:
commit
c0f51c292a
68
CHANGELOG.md
68
CHANGELOG.md
@ -1,3 +1,66 @@
|
||||
## 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
|
||||
that style rule rather than at the root of the document.
|
||||
|
||||
## 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.
|
||||
|
||||
* **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`.
|
||||
|
||||
* **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
|
||||
|
||||
* **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.
|
||||
|
||||
* **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.
|
||||
|
||||
* 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.
|
||||
|
||||
* 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.
|
||||
|
||||
* 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
|
||||
|
||||
* Avoid re-assigning the `require()` function to make the code statically
|
||||
analyzable by Webpack.
|
||||
|
||||
## 1.22.1
|
||||
|
||||
### JavaScript API
|
||||
@ -27,11 +90,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.
|
||||
|
@ -47,16 +47,20 @@ final global = UnmodifiableListView([
|
||||
}
|
||||
}),
|
||||
|
||||
BuiltInCallable("invert", r"$color, $weight: 50%", (arguments) {
|
||||
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);
|
||||
if (weight.value == 50) return inverse;
|
||||
|
||||
return _mixColors(inverse, color, weight);
|
||||
}),
|
||||
@ -130,8 +134,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) {
|
||||
@ -171,17 +175,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.");
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
@ -206,8 +216,14 @@ final module = BuiltInModule("color", functions: [
|
||||
// ### RGB
|
||||
_red, _green, _blue, _mix,
|
||||
|
||||
BuiltInCallable("invert", r"$color, $weight: 50%", (arguments) {
|
||||
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"
|
||||
@ -216,10 +232,8 @@ final module = BuiltInModule("color", functions: [
|
||||
}
|
||||
|
||||
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);
|
||||
if (weight.value == 50) return inverse;
|
||||
|
||||
return _mixColors(inverse, color, weight);
|
||||
}),
|
||||
@ -400,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 {
|
||||
|
@ -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];
|
||||
@ -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 = <SassList>[];
|
||||
while (lists.every((list) => i != list.length)) {
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
@ -113,7 +116,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);
|
||||
});
|
||||
|
||||
|
@ -74,7 +74,7 @@ void ensureDir(String path) => io.Directory(path).createSync(recursive: true);
|
||||
Iterable<String> listDir(String path, {bool recursive = false}) =>
|
||||
io.Directory(path)
|
||||
.listSync(recursive: recursive)
|
||||
.where((entity) => entity is io.File)
|
||||
.whereType<io.File>()
|
||||
.map((entity) => entity.path);
|
||||
|
||||
DateTime modificationTime(String path) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,11 @@ bool startsWithIgnoreSeparator(String string, String prefix) {
|
||||
/// If [source] is passed, copies it into the map.
|
||||
Map<String, V> normalizedMap<V>([Map<String, V> source]) {
|
||||
var map = LinkedHashMap<String, V>(
|
||||
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<String, V> normalizedMap<V>([Map<String, V> source]) {
|
||||
/// If [source] is passed, copies it into the set.
|
||||
Set<String> normalizedSet([Iterable<String> 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;
|
||||
}
|
||||
|
@ -10,7 +10,8 @@ import 'external/value.dart' as ext;
|
||||
class SassMap extends Value implements ext.SassMap {
|
||||
final Map<Value, Value> contents;
|
||||
|
||||
ListSeparator get separator => ListSeparator.comma;
|
||||
ListSeparator get separator =>
|
||||
contents.isEmpty ? ListSeparator.undecided : ListSeparator.comma;
|
||||
|
||||
List<Value> get asList {
|
||||
var result = <Value>[];
|
||||
|
@ -2133,15 +2133,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<String, Expression, Value>(
|
||||
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<String, Expression, String, AstNode>(arguments.named,
|
||||
value: (_, expression) => _expressionNode(expression))
|
||||
@ -2796,7 +2800,10 @@ class _ImportedCssVisitor implements ModifiableCssVisitor<void> {
|
||||
|
||||
_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);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||
// See tool/grind/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: 2dc9fdf171d8c876f24994eb0e106328154497c4
|
||||
// Checksum: f6ac9bc98278f8019357f5d6d56d46f46636f4bc
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
@ -2119,14 +2119,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<String, Expression, Value>(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<String, Expression, String, AstNode>(arguments.named,
|
||||
value: (_, expression) => _expressionNode(expression))
|
||||
@ -2760,7 +2764,10 @@ class _ImportedCssVisitor implements ModifiableCssVisitor<void> {
|
||||
|
||||
_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);
|
||||
|
||||
|
148
perf.md
148
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 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,148 +20,150 @@ 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
|
||||
* 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:
|
||||
|
||||
* 3.5x slower than libsass
|
||||
* 12.1x faster than Dart Sass on Node
|
||||
* 10.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.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.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.3x faster than libsass
|
||||
* 2.1x faster than Dart Sass on Node
|
||||
* 7.5x faster than Ruby Sass
|
||||
* 1.1x faster than libsass
|
||||
* 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: 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.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.4x faster than libsass
|
||||
* 2.1x faster than Dart Sass on Node
|
||||
* 11.3x faster than Ruby Sass
|
||||
* 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.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.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:
|
||||
|
||||
* 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.8x faster than Dart Sass on Node
|
||||
* 10.7x 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.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.2x slower than libsass
|
||||
* 2.7x faster than Dart Sass on Node
|
||||
* 12.4x faster than Ruby Sass
|
||||
* 1.1x slower than libsass
|
||||
* 2.2x faster than Dart Sass on Node
|
||||
* 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.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.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
|
||||
* 3.0x faster than Dart Sass on Node
|
||||
* 12.7x faster than Ruby Sass
|
||||
* 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.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.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:
|
||||
|
||||
* identical to libsass
|
||||
* 3.9x faster than Dart Sass on Node
|
||||
* 13.9x faster than Ruby Sass
|
||||
* 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.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.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:
|
||||
|
||||
* 1.7x slower than libsass
|
||||
* 3.6x faster than Dart Sass on Node
|
||||
* 8.9x faster than Ruby Sass
|
||||
* 2.3x slower than libsass
|
||||
* 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.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.248s
|
||||
* Dart Sass from a script snapshot: 0.673s
|
||||
* 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:
|
||||
|
||||
* 1.3x faster than libsass
|
||||
* 5.7x faster than Dart Sass on Node
|
||||
* 6.7x faster than Ruby Sass
|
||||
* identical to libsass
|
||||
* 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).
|
||||
* [1.0.0-alpha.8](https://github.com/sass/dart-sass/blob/be44245a849f2bb18b5ca1fc74f3043a36da17f0/perf.md).
|
||||
|
@ -1,5 +1,5 @@
|
||||
name: sass
|
||||
version: 1.22.1
|
||||
version: 1.22.5
|
||||
description: A Sass implementation in Dart.
|
||||
author: Dart Team <misc@dartlang.org>
|
||||
homepage: https://github.com/sass/dart-sass
|
||||
|
@ -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", () {
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user