mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-26 20:24:42 +01:00
Use the new Dart 2.3.0 literal syntax (#684)
This commit is contained in:
parent
819d357cb8
commit
db87ed2f0e
@ -54,8 +54,8 @@ class CssMediaQuery {
|
||||
var theirType = other.type?.toLowerCase();
|
||||
|
||||
if (ourType == null && theirType == null) {
|
||||
return MediaQuerySuccessfulMergeResult._(CssMediaQuery.condition(
|
||||
this.features.toList()..addAll(other.features)));
|
||||
return MediaQuerySuccessfulMergeResult._(
|
||||
CssMediaQuery.condition([...this.features, ...other.features]));
|
||||
}
|
||||
|
||||
String modifier;
|
||||
@ -120,17 +120,17 @@ class CssMediaQuery {
|
||||
// Omit the type if either input query did, since that indicates that they
|
||||
// aren't targeting a browser that requires "all and".
|
||||
type = (other.matchesAllTypes && ourType == null) ? null : theirType;
|
||||
features = this.features.toList()..addAll(other.features);
|
||||
features = [...this.features, ...other.features];
|
||||
} else if (other.matchesAllTypes) {
|
||||
modifier = ourModifier;
|
||||
type = ourType;
|
||||
features = this.features.toList()..addAll(other.features);
|
||||
features = [...this.features, ...other.features];
|
||||
} else if (ourType != theirType) {
|
||||
return MediaQueryMergeResult.empty;
|
||||
} else {
|
||||
modifier = ourModifier ?? theirModifier;
|
||||
type = ourType;
|
||||
features = this.features.toList()..addAll(other.features);
|
||||
features = [...this.features, ...other.features];
|
||||
}
|
||||
|
||||
return MediaQuerySuccessfulMergeResult._(CssMediaQuery(
|
||||
|
@ -100,9 +100,8 @@ class ArgumentDeclaration implements SassNode {
|
||||
return true;
|
||||
}
|
||||
|
||||
String toString() {
|
||||
var components = List.of(arguments.map((arg) => arg.toString()));
|
||||
if (restArgument != null) components.add('$restArgument...');
|
||||
return components.join(', ');
|
||||
}
|
||||
String toString() => [
|
||||
for (var arg in arguments) arg.toString(),
|
||||
if (restArgument != null) '$restArgument...'
|
||||
].join(', ');
|
||||
}
|
||||
|
@ -42,10 +42,12 @@ class ArgumentInvocation implements SassNode {
|
||||
keywordRest = null;
|
||||
|
||||
String toString() {
|
||||
var components = List<Object>.from(positional)
|
||||
..addAll(named.keys.map((name) => "$name: ${named[name]}"));
|
||||
if (rest != null) components.add("$rest...");
|
||||
if (keywordRest != null) components.add("$keywordRest...");
|
||||
var components = [
|
||||
...positional,
|
||||
for (var name in named.keys) "$name: ${named[name]}",
|
||||
if (rest != null) "$rest...",
|
||||
if (keywordRest != null) "$keywordRest..."
|
||||
];
|
||||
return "(${components.join(', ')})";
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class SelectorList extends Selector {
|
||||
if (!_complexContainsParentSelector(complex)) {
|
||||
if (!implicitParent) return [complex];
|
||||
return parent.components.map((parentComplex) => ComplexSelector(
|
||||
parentComplex.components.toList()..addAll(complex.components),
|
||||
[...parentComplex.components, ...complex.components],
|
||||
lineBreak: complex.lineBreak || parentComplex.lineBreak));
|
||||
}
|
||||
|
||||
@ -127,8 +127,7 @@ class SelectorList extends Selector {
|
||||
for (var newComplex in previousComplexes) {
|
||||
var lineBreak = previousLineBreaks[i++];
|
||||
for (var resolvedComplex in resolved) {
|
||||
newComplexes
|
||||
.add(newComplex.toList()..addAll(resolvedComplex.components));
|
||||
newComplexes.add([...newComplex, ...resolvedComplex.components]);
|
||||
lineBreaks.add(lineBreak || resolvedComplex.lineBreak);
|
||||
}
|
||||
}
|
||||
@ -204,18 +203,18 @@ class SelectorList extends Selector {
|
||||
var last = lastComponent as CompoundSelector;
|
||||
var suffix = (compound.components.first as ParentSelector).suffix;
|
||||
if (suffix != null) {
|
||||
last = CompoundSelector(
|
||||
last.components.take(last.components.length - 1).toList()
|
||||
..add(last.components.last.addSuffix(suffix))
|
||||
..addAll(resolvedMembers.skip(1)));
|
||||
last = CompoundSelector([
|
||||
...last.components.take(last.components.length - 1),
|
||||
last.components.last.addSuffix(suffix),
|
||||
...resolvedMembers.skip(1)
|
||||
]);
|
||||
} else {
|
||||
last = CompoundSelector(
|
||||
last.components.toList()..addAll(resolvedMembers.skip(1)));
|
||||
last =
|
||||
CompoundSelector([...last.components, ...resolvedMembers.skip(1)]);
|
||||
}
|
||||
|
||||
return ComplexSelector(
|
||||
complex.components.take(complex.components.length - 1).toList()
|
||||
..add(last),
|
||||
[...complex.components.take(complex.components.length - 1), last],
|
||||
lineBreak: complex.lineBreak);
|
||||
});
|
||||
}
|
||||
|
@ -25,9 +25,9 @@ class TypeSelector extends SimpleSelector {
|
||||
if (compound.first is UniversalSelector || compound.first is TypeSelector) {
|
||||
var unified = unifyUniversalAndElement(this, compound.first);
|
||||
if (unified == null) return null;
|
||||
return [unified]..addAll(compound.skip(1));
|
||||
return [unified, ...compound.skip(1)];
|
||||
} else {
|
||||
return <SimpleSelector>[this]..addAll(compound);
|
||||
return [this, ...compound];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,12 +27,10 @@ class UniversalSelector extends SimpleSelector {
|
||||
if (compound.first is UniversalSelector || compound.first is TypeSelector) {
|
||||
var unified = unifyUniversalAndElement(this, compound.first);
|
||||
if (unified == null) return null;
|
||||
return [unified]..addAll(compound.skip(1));
|
||||
return [unified, ...compound.skip(1)];
|
||||
}
|
||||
|
||||
if (namespace != null && namespace != "*") {
|
||||
return <SimpleSelector>[this]..addAll(compound);
|
||||
}
|
||||
if (namespace != null && namespace != "*") return [this, ...compound];
|
||||
if (compound.isNotEmpty) return compound;
|
||||
return [this];
|
||||
}
|
||||
|
@ -77,24 +77,16 @@ class AsyncImportCache {
|
||||
/// options into a single list of importers.
|
||||
static List<AsyncImporter> _toImporters(Iterable<AsyncImporter> importers,
|
||||
Iterable<String> loadPaths, SyncPackageResolver packageResolver) {
|
||||
var list = importers?.toList() ?? [];
|
||||
|
||||
if (loadPaths != null) {
|
||||
list.addAll(loadPaths.map((path) => FilesystemImporter(path)));
|
||||
}
|
||||
|
||||
var sassPath = getEnvironmentVariable('SASS_PATH');
|
||||
if (sassPath != null) {
|
||||
list.addAll(sassPath
|
||||
.split(isWindows ? ';' : ':')
|
||||
.map((path) => FilesystemImporter(path)));
|
||||
}
|
||||
|
||||
if (packageResolver != null) {
|
||||
list.add(PackageImporter(packageResolver));
|
||||
}
|
||||
|
||||
return list;
|
||||
return [
|
||||
...?importers,
|
||||
if (loadPaths != null)
|
||||
for (var path in loadPaths) FilesystemImporter(path),
|
||||
if (sassPath != null)
|
||||
for (var path in sassPath.split(isWindows ? ';' : ':'))
|
||||
FilesystemImporter(path),
|
||||
if (packageResolver != null) PackageImporter(packageResolver)
|
||||
];
|
||||
}
|
||||
|
||||
/// Creates a cache that contains no importers.
|
||||
|
@ -371,18 +371,19 @@ class ExecutableOptions {
|
||||
/// Returns the sub-map of [sourcesToDestinations] for the given [source] and
|
||||
/// [destination] directories.
|
||||
Map<String, String> _listSourceDirectory(String source, String destination) {
|
||||
var map = <String, String>{};
|
||||
for (var path in listDir(source, recursive: true)) {
|
||||
var basename = p.basename(path);
|
||||
if (basename.startsWith("_")) continue;
|
||||
return {
|
||||
for (var path in listDir(source, recursive: true))
|
||||
if (_isEntrypoint(path))
|
||||
path: p.join(destination,
|
||||
p.setExtension(p.relative(path, from: source), '.css'))
|
||||
};
|
||||
}
|
||||
|
||||
var extension = p.extension(path);
|
||||
if (extension != ".scss" && extension != ".sass") continue;
|
||||
|
||||
map[path] = p.join(
|
||||
destination, p.setExtension(p.relative(path, from: source), '.css'));
|
||||
}
|
||||
return map;
|
||||
/// Returns whether [path] is a Sass entrypoint (that is, not a partial).
|
||||
bool _isEntrypoint(String path) {
|
||||
if (p.basename(path).startsWith("_")) return false;
|
||||
var extension = p.extension(path);
|
||||
return extension == ".scss" || extension == ".sass";
|
||||
}
|
||||
|
||||
/// Whether to emit a source map file.
|
||||
|
@ -20,10 +20,11 @@ import 'options.dart';
|
||||
|
||||
/// Watches all the files in [graph] for changes and updates them as necessary.
|
||||
Future watch(ExecutableOptions options, StylesheetGraph graph) async {
|
||||
var directoriesToWatch = <String>[]
|
||||
..addAll(options.sourceDirectoriesToDestinations.keys)
|
||||
..addAll(options.sourcesToDestinations.keys.map(p.dirname))
|
||||
..addAll(options.loadPaths);
|
||||
var directoriesToWatch = [
|
||||
...options.sourceDirectoriesToDestinations.keys,
|
||||
...options.sourcesToDestinations.keys.map(p.dirname),
|
||||
...options.loadPaths
|
||||
];
|
||||
|
||||
var dirWatcher = MultiDirWatcher(poll: options.poll);
|
||||
await Future.wait(directoriesToWatch.map((dir) {
|
||||
|
@ -96,11 +96,10 @@ class Extender {
|
||||
throw SassScriptException("Can't extend complex selector $complex.");
|
||||
}
|
||||
|
||||
var extensions = <SimpleSelector, Map<ComplexSelector, Extension>>{};
|
||||
var compound = complex.components.first as CompoundSelector;
|
||||
for (var simple in compound.components) {
|
||||
extensions[simple] = extenders;
|
||||
}
|
||||
var extensions = {
|
||||
for (var simple in compound.components) simple: extenders
|
||||
};
|
||||
|
||||
var extender = Extender._mode(mode);
|
||||
if (!selector.isInvisible) {
|
||||
@ -702,10 +701,7 @@ class Extender {
|
||||
targetsUsed?.add(simple);
|
||||
if (_mode == ExtendMode.replace) return extenders.values.toList();
|
||||
|
||||
var extenderList = List<Extension>(extenders.length + 1);
|
||||
extenderList[0] = _extensionForSimple(simple);
|
||||
extenderList.setRange(1, extenderList.length, extenders.values);
|
||||
return extenderList;
|
||||
return [_extensionForSimple(simple), ...extenders.values];
|
||||
}
|
||||
|
||||
if (simple is PseudoSelector && simple.selector != null) {
|
||||
|
@ -21,8 +21,7 @@ import '../utils.dart';
|
||||
/// subselectors of their arguments.
|
||||
///
|
||||
/// For example, `.foo` is a superselector of `:matches(.foo)`.
|
||||
final _subselectorPseudos =
|
||||
Set.of(['matches', 'any', 'nth-child', 'nth-last-child']);
|
||||
final _subselectorPseudos = {'matches', 'any', 'nth-child', 'nth-last-child'};
|
||||
|
||||
/// Returns the contents of a [SelectorList] that matches only elements that are
|
||||
/// matched by both [complex1] and [complex2].
|
||||
@ -381,18 +380,16 @@ List<List<List<ComplexSelectorComponent>>> _mergeFinalCombinators(
|
||||
[nextSiblingSelector, Combinator.nextSibling]
|
||||
]);
|
||||
} else {
|
||||
var choices = [
|
||||
var unified = unifyCompound(compound1.components, compound2.components);
|
||||
result.addFirst([
|
||||
[
|
||||
followingSiblingSelector,
|
||||
Combinator.followingSibling,
|
||||
nextSiblingSelector,
|
||||
Combinator.nextSibling
|
||||
]
|
||||
];
|
||||
|
||||
var unified = unifyCompound(compound1.components, compound2.components);
|
||||
if (unified != null) choices.add([unified, Combinator.nextSibling]);
|
||||
result.addFirst(choices);
|
||||
],
|
||||
if (unified != null) [unified, Combinator.nextSibling]
|
||||
]);
|
||||
}
|
||||
} else if (combinator1 == Combinator.child &&
|
||||
(combinator2 == Combinator.nextSibling ||
|
||||
@ -451,12 +448,11 @@ List<List<List<ComplexSelectorComponent>>> _mergeFinalCombinators(
|
||||
/// selector, such as an ID.
|
||||
bool _mustUnify(List<ComplexSelectorComponent> complex1,
|
||||
List<ComplexSelectorComponent> complex2) {
|
||||
var uniqueSelectors = Set<SimpleSelector>();
|
||||
for (var component in complex1) {
|
||||
if (component is CompoundSelector) {
|
||||
uniqueSelectors.addAll(component.components.where(_isUnique));
|
||||
}
|
||||
}
|
||||
var uniqueSelectors = {
|
||||
for (var component in complex1)
|
||||
if (component is CompoundSelector)
|
||||
...component.components.where(_isUnique)
|
||||
};
|
||||
if (uniqueSelectors.isEmpty) return false;
|
||||
|
||||
return complex2.any((component) =>
|
||||
@ -496,7 +492,10 @@ List<List<T>> _chunks<T>(
|
||||
if (chunk1.isEmpty && chunk2.isEmpty) return [];
|
||||
if (chunk1.isEmpty) return [chunk2];
|
||||
if (chunk2.isEmpty) return [chunk1];
|
||||
return [chunk1.toList()..addAll(chunk2), chunk2..addAll(chunk1)];
|
||||
return [
|
||||
[...chunk1, ...chunk2],
|
||||
[...chunk2, ...chunk1]
|
||||
];
|
||||
}
|
||||
|
||||
/// Returns a list of all possible paths through the given lists.
|
||||
@ -512,7 +511,7 @@ List<List<T>> _chunks<T>(
|
||||
List<List<T>> paths<T>(Iterable<List<T>> choices) => choices.fold(
|
||||
[[]],
|
||||
(paths, choice) => choice
|
||||
.expand((option) => paths.map((path) => path.toList()..add(option)))
|
||||
.expand((option) => paths.map((path) => [...path, option]))
|
||||
.toList());
|
||||
|
||||
/// Returns [complex], grouped into sub-lists such that no sub-list contains two
|
||||
@ -566,8 +565,7 @@ bool complexIsParentSuperselector(List<ComplexSelectorComponent> complex1,
|
||||
// TODO(nweiz): There's got to be a way to do this without a bunch of extra
|
||||
// allocations...
|
||||
var base = CompoundSelector([PlaceholderSelector('<temp>')]);
|
||||
return complexIsSuperselector(
|
||||
complex1.toList()..add(base), complex2.toList()..add(base));
|
||||
return complexIsSuperselector([...complex1, base], [...complex2, base]);
|
||||
}
|
||||
|
||||
/// Returns whether [complex1] is a superselector of [complex2].
|
||||
@ -732,11 +730,8 @@ bool _selectorPseudoIsSuperselector(
|
||||
return pseudos.any((pseudo2) {
|
||||
return pseudo1.selector.isSuperselector(pseudo2.selector);
|
||||
}) ||
|
||||
pseudo1.selector.components.any((complex1) {
|
||||
var complex2 = (parents?.toList() ?? <ComplexSelectorComponent>[])
|
||||
..add(compound2);
|
||||
return complexIsSuperselector(complex1.components, complex2);
|
||||
});
|
||||
pseudo1.selector.components.any((complex1) => complexIsSuperselector(
|
||||
complex1.components, [...?parents, compound2]));
|
||||
|
||||
case 'has':
|
||||
case 'host':
|
||||
|
@ -21,13 +21,13 @@ import 'value.dart';
|
||||
final _microsoftFilterStart = RegExp(r'^[a-zA-Z]+\s*=');
|
||||
|
||||
/// Feature names supported by Dart sass.
|
||||
final _features = Set.of([
|
||||
final _features = {
|
||||
"global-variable-shadowing",
|
||||
"extend-selector-pseudoclass",
|
||||
"units-level-3",
|
||||
"at-error",
|
||||
"custom-property"
|
||||
]);
|
||||
};
|
||||
|
||||
/// A random number generator.
|
||||
final _random = math.Random();
|
||||
@ -627,7 +627,7 @@ final List<BuiltInCallable> coreFunctions = UnmodifiableListView([
|
||||
? list1.hasBrackets
|
||||
: bracketedParam.isTruthy;
|
||||
|
||||
var newList = list1.asList.toList()..addAll(list2.asList);
|
||||
var newList = [...list1.asList, ...list2.asList];
|
||||
return SassList(newList, separator, brackets: bracketed);
|
||||
}),
|
||||
|
||||
@ -650,7 +650,7 @@ final List<BuiltInCallable> coreFunctions = UnmodifiableListView([
|
||||
'\$$separator: Must be "space", "comma", or "auto".');
|
||||
}
|
||||
|
||||
var newList = list.asList.toList()..add(value);
|
||||
var newList = [...list.asList, value];
|
||||
return list.changeListContents(newList, separator: separator);
|
||||
}),
|
||||
|
||||
@ -694,7 +694,7 @@ final List<BuiltInCallable> coreFunctions = UnmodifiableListView([
|
||||
BuiltInCallable("map-merge", r"$map1, $map2", (arguments) {
|
||||
var map1 = arguments[0].assertMap("map1");
|
||||
var map2 = arguments[1].assertMap("map2");
|
||||
return SassMap(Map.of(map1.contents)..addAll(map2.contents));
|
||||
return SassMap({...map1.contents, ...map2.contents});
|
||||
}),
|
||||
|
||||
BuiltInCallable("map-remove", r"$map, $keys...", (arguments) {
|
||||
@ -769,8 +769,7 @@ final List<BuiltInCallable> coreFunctions = UnmodifiableListView([
|
||||
throw SassScriptException("Can't append $complex to $parent.");
|
||||
}
|
||||
|
||||
return ComplexSelector(<ComplexSelectorComponent>[newCompound]
|
||||
..addAll(complex.components.skip(1)));
|
||||
return ComplexSelector([newCompound, ...complex.components.skip(1)]);
|
||||
} else {
|
||||
throw SassScriptException("Can't append $complex to $parent.");
|
||||
}
|
||||
@ -1139,12 +1138,12 @@ CompoundSelector _prependParent(CompoundSelector compound) {
|
||||
if (first is UniversalSelector) return null;
|
||||
if (first is TypeSelector) {
|
||||
if (first.name.namespace != null) return null;
|
||||
return CompoundSelector(<SimpleSelector>[
|
||||
ParentSelector(suffix: first.name.name)
|
||||
]..addAll(compound.components.skip(1)));
|
||||
return CompoundSelector([
|
||||
ParentSelector(suffix: first.name.name),
|
||||
...compound.components.skip(1)
|
||||
]);
|
||||
} else {
|
||||
return CompoundSelector(
|
||||
<SimpleSelector>[ParentSelector()]..addAll(compound.components));
|
||||
return CompoundSelector([ParentSelector(), ...compound.components]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_import_cache.dart.
|
||||
// See tool/grind/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: 291afac7e0d5edc6610685b28741786f667f83e8
|
||||
// Checksum: 1e51fceaa60c0a65fa9c447cfe25eda5109a819f
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
@ -82,24 +82,16 @@ class ImportCache {
|
||||
/// options into a single list of importers.
|
||||
static List<Importer> _toImporters(Iterable<Importer> importers,
|
||||
Iterable<String> loadPaths, SyncPackageResolver packageResolver) {
|
||||
var list = importers?.toList() ?? [];
|
||||
|
||||
if (loadPaths != null) {
|
||||
list.addAll(loadPaths.map((path) => FilesystemImporter(path)));
|
||||
}
|
||||
|
||||
var sassPath = getEnvironmentVariable('SASS_PATH');
|
||||
if (sassPath != null) {
|
||||
list.addAll(sassPath
|
||||
.split(isWindows ? ';' : ':')
|
||||
.map((path) => FilesystemImporter(path)));
|
||||
}
|
||||
|
||||
if (packageResolver != null) {
|
||||
list.add(PackageImporter(packageResolver));
|
||||
}
|
||||
|
||||
return list;
|
||||
return [
|
||||
...?importers,
|
||||
if (loadPaths != null)
|
||||
for (var path in loadPaths) FilesystemImporter(path),
|
||||
if (sassPath != null)
|
||||
for (var path in sassPath.split(isWindows ? ';' : ':'))
|
||||
FilesystemImporter(path),
|
||||
if (packageResolver != null) PackageImporter(packageResolver)
|
||||
];
|
||||
}
|
||||
|
||||
/// Creates a cache that contains no importers.
|
||||
|
@ -68,11 +68,8 @@ List<String> _tryPathWithExtensions(String path) {
|
||||
///
|
||||
/// If neither exists, returns an empty list.
|
||||
List<String> _tryPath(String path) {
|
||||
var paths = <String>[];
|
||||
var partial = p.join(p.dirname(path), "_${p.basename(path)}");
|
||||
if (fileExists(partial)) paths.add(partial);
|
||||
if (fileExists(path)) paths.add(path);
|
||||
return paths;
|
||||
return [if (fileExists(partial)) partial, if (fileExists(path)) path];
|
||||
}
|
||||
|
||||
/// Returns the resolved index file for [path] if [path] is a directory and the
|
||||
|
@ -70,9 +70,8 @@ class InterpolationBuffer implements StringSink {
|
||||
/// Creates an [Interpolation] with the given [span] from the contents of this
|
||||
/// buffer.
|
||||
Interpolation interpolation(FileSpan span) {
|
||||
var contents = _contents.toList();
|
||||
if (_text.isNotEmpty) contents.add(_text.toString());
|
||||
return Interpolation(contents, span);
|
||||
return Interpolation(
|
||||
[..._contents, if (_text.isNotEmpty) _text.toString()], span);
|
||||
}
|
||||
|
||||
String toString() {
|
||||
|
@ -204,12 +204,14 @@ List<AsyncCallable> _parseFunctions(RenderOptions options,
|
||||
if (options.fiber != null) {
|
||||
result.add(BuiltInCallable.parsed(tuple.item1, tuple.item2, (arguments) {
|
||||
var fiber = options.fiber.current;
|
||||
var jsArguments = arguments.map(wrapValue).toList()
|
||||
..add(allowInterop(([result]) {
|
||||
var jsArguments = [
|
||||
...arguments.map(wrapValue),
|
||||
allowInterop(([result]) {
|
||||
// Schedule a microtask so we don't try to resume the running fiber
|
||||
// if [importer] calls `done()` synchronously.
|
||||
scheduleMicrotask(() => fiber.run(result));
|
||||
}));
|
||||
})
|
||||
];
|
||||
var result = Function.apply(callback as Function, jsArguments);
|
||||
return unwrapValue(
|
||||
isUndefined(result) ? options.fiber.yield() : result);
|
||||
@ -224,8 +226,10 @@ List<AsyncCallable> _parseFunctions(RenderOptions options,
|
||||
result.add(AsyncBuiltInCallable.parsed(tuple.item1, tuple.item2,
|
||||
(arguments) async {
|
||||
var completer = Completer();
|
||||
var jsArguments = arguments.map(wrapValue).toList()
|
||||
..add(allowInterop(([result]) => completer.complete(result)));
|
||||
var jsArguments = [
|
||||
...arguments.map(wrapValue),
|
||||
allowInterop(([result]) => completer.complete(result))
|
||||
];
|
||||
var result = Function.apply(callback as Function, jsArguments);
|
||||
return unwrapValue(
|
||||
isUndefined(result) ? await completer.future : result);
|
||||
@ -256,7 +260,7 @@ NodeImporter _parseImporter(RenderOptions options, DateTime start) {
|
||||
file: options.file,
|
||||
data: options.data,
|
||||
includePaths:
|
||||
([p.current]..addAll(includePaths)).join(isWindows ? ';' : ':'),
|
||||
([p.current, ...includePaths]).join(isWindows ? ';' : ':'),
|
||||
precision: SassNumber.precision,
|
||||
style: 1,
|
||||
indentType: options.indentType == 'tab' ? 1 : 0,
|
||||
|
@ -55,10 +55,8 @@ final Function mapConstructor =
|
||||
},
|
||||
'setValue': (_NodeSassMap thisArg, int index, value) {
|
||||
var key = thisArg.dartValue.contents.keys.elementAt(index);
|
||||
|
||||
var mutable = Map.of(thisArg.dartValue.contents);
|
||||
mutable[key] = unwrapValue(value);
|
||||
thisArg.dartValue = SassMap(mutable);
|
||||
thisArg.dartValue =
|
||||
SassMap({...thisArg.dartValue.contents, key: unwrapValue(value)});
|
||||
},
|
||||
'toString': (_NodeSassMap thisArg) => thisArg.dartValue.toString()
|
||||
});
|
||||
|
@ -11,11 +11,18 @@ import '../utils.dart';
|
||||
import 'parser.dart';
|
||||
|
||||
/// Pseudo-class selectors that take unadorned selectors as arguments.
|
||||
final _selectorPseudoClasses =
|
||||
Set.of(["not", "matches", "current", "any", "has", "host", "host-context"]);
|
||||
final _selectorPseudoClasses = {
|
||||
"not",
|
||||
"matches",
|
||||
"current",
|
||||
"any",
|
||||
"has",
|
||||
"host",
|
||||
"host-context"
|
||||
};
|
||||
|
||||
/// Pseudo-element selectors that take unadorned selectors as arguments.
|
||||
final _selectorPseudoElements = Set.of(["slotted"]);
|
||||
final _selectorPseudoElements = {"slotted"};
|
||||
|
||||
/// A parser for selectors.
|
||||
class SelectorParser extends Parser {
|
||||
|
@ -94,13 +94,13 @@ class StylesheetGraph {
|
||||
/// appears within [baseUrl] imported by [baseImporter].
|
||||
Map<Uri, StylesheetNode> _upstreamNodes(
|
||||
Stylesheet stylesheet, Importer baseImporter, Uri baseUrl) {
|
||||
var active = Set.of([baseUrl]);
|
||||
var upstream = <Uri, StylesheetNode>{};
|
||||
for (var import in findImports(stylesheet)) {
|
||||
var url = Uri.parse(import.url);
|
||||
upstream[url] = _nodeFor(url, baseImporter, baseUrl, active);
|
||||
}
|
||||
return upstream;
|
||||
var active = {baseUrl};
|
||||
var upstreamUrls =
|
||||
findImports(stylesheet).map((import) => Uri.parse(import.url));
|
||||
return {
|
||||
for (var url in upstreamUrls)
|
||||
url: _nodeFor(url, baseImporter, baseUrl, active)
|
||||
};
|
||||
}
|
||||
|
||||
/// Re-parses the stylesheet at [canonicalUrl] and updates the dependency graph
|
||||
|
@ -406,13 +406,8 @@ void rotateSlice(List list, int start, int end) {
|
||||
|
||||
/// Like [Iterable.map] but for an asynchronous [callback].
|
||||
Future<Iterable<F>> mapAsync<E, F>(
|
||||
Iterable<E> iterable, Future<F> callback(E value)) async {
|
||||
var result = <F>[];
|
||||
for (var element in iterable) {
|
||||
result.add(await callback(element));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Iterable<E> iterable, Future<F> callback(E value)) async =>
|
||||
[for (var element in iterable) await callback(element)];
|
||||
|
||||
/// Like [Map.putIfAbsent], but for an asynchronous [ifAbsent].
|
||||
///
|
||||
|
@ -1072,8 +1072,7 @@ class _EvaluateVisitor
|
||||
throw "Can't find stylesheet to import.";
|
||||
}
|
||||
} on SassException catch (error) {
|
||||
var frames = error.trace.frames.toList()
|
||||
..addAll(_stackTrace(span).frames);
|
||||
var frames = [...error.trace.frames, ..._stackTrace(span).frames];
|
||||
throw SassRuntimeException(error.message, error.span, Trace(frames));
|
||||
} catch (error) {
|
||||
String message;
|
||||
@ -2416,10 +2415,10 @@ class _EvaluateVisitor
|
||||
///
|
||||
/// [span] is the current location, used for the bottom-most stack frame.
|
||||
Trace _stackTrace(FileSpan span) {
|
||||
var frames = _stack
|
||||
.map((tuple) => _stackFrame(tuple.item1, tuple.item2.span))
|
||||
.toList()
|
||||
..add(_stackFrame(_member, span));
|
||||
var frames = [
|
||||
..._stack.map((tuple) => _stackFrame(tuple.item1, tuple.item2.span)),
|
||||
_stackFrame(_member, span)
|
||||
];
|
||||
return Trace(frames.reversed);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||
// See tool/grind/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: c41c933bbae5af96a77e39cea8c4d7a4c86cb564
|
||||
// Checksum: 71e3dfeef2683bd246e21ddfd25b21df408cf18e
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
@ -1074,8 +1074,7 @@ class _EvaluateVisitor
|
||||
throw "Can't find stylesheet to import.";
|
||||
}
|
||||
} on SassException catch (error) {
|
||||
var frames = error.trace.frames.toList()
|
||||
..addAll(_stackTrace(span).frames);
|
||||
var frames = [...error.trace.frames, ..._stackTrace(span).frames];
|
||||
throw SassRuntimeException(error.message, error.span, Trace(frames));
|
||||
} catch (error) {
|
||||
String message;
|
||||
@ -2393,10 +2392,10 @@ class _EvaluateVisitor
|
||||
///
|
||||
/// [span] is the current location, used for the bottom-most stack frame.
|
||||
Trace _stackTrace(FileSpan span) {
|
||||
var frames = _stack
|
||||
.map((tuple) => _stackFrame(tuple.item1, tuple.item2.span))
|
||||
.toList()
|
||||
..add(_stackFrame(_member, span));
|
||||
var frames = [
|
||||
..._stack.map((tuple) => _stackFrame(tuple.item1, tuple.item2.span)),
|
||||
_stackFrame(_member, span)
|
||||
];
|
||||
return Trace(frames.reversed);
|
||||
}
|
||||
|
||||
|
@ -50,16 +50,17 @@ Future<TestProcess> runSass(Iterable<String> arguments,
|
||||
var executable = _snapshotPaths.firstWhere((path) => File(path).existsSync(),
|
||||
orElse: () => p.absolute("bin/sass.dart"));
|
||||
|
||||
var args = ["--enable-asserts"];
|
||||
|
||||
// Work around dart-lang/sdk#33622.
|
||||
if (Platform.isWindows) args.add("--packages=${p.absolute('.packages')}");
|
||||
|
||||
return TestProcess.start(
|
||||
Platform.executable,
|
||||
args
|
||||
..add(executable)
|
||||
..addAll(arguments),
|
||||
[
|
||||
"--enable-asserts",
|
||||
// Work around dart-lang/sdk#33622.
|
||||
if (Platform.isWindows)
|
||||
"--packages=${p.absolute('.packages')}",
|
||||
|
||||
executable,
|
||||
...arguments
|
||||
],
|
||||
workingDirectory: d.sandbox,
|
||||
environment: environment,
|
||||
description: "sass");
|
||||
|
@ -32,8 +32,7 @@ void main() {
|
||||
|
||||
Future<TestProcess> runSass(Iterable<String> arguments,
|
||||
{Map<String, String> environment}) =>
|
||||
TestProcess.start(
|
||||
"node", [p.absolute("build/npm/sass.js")]..addAll(arguments),
|
||||
TestProcess.start("node", [p.absolute("build/npm/sass.js"), ...arguments],
|
||||
workingDirectory: d.sandbox,
|
||||
environment: environment,
|
||||
description: "sass");
|
||||
|
@ -19,8 +19,7 @@ void sharedTests(
|
||||
/// the contents of the output file match [expected].
|
||||
Future expectCompiles(List<String> arguments, expected,
|
||||
{Map<String, String> environment}) async {
|
||||
var sass = await runSass(
|
||||
arguments.toList()..add("out.css")..add("--no-source-map"),
|
||||
var sass = await runSass([...arguments, "out.css", "--no-source-map"],
|
||||
environment: environment);
|
||||
await sass.shouldExit(0);
|
||||
await d.file("out.css", expected).validate();
|
||||
|
@ -13,7 +13,7 @@ import '../../utils.dart';
|
||||
/// Defines test that are shared between the Dart and Node.js CLI test suites.
|
||||
void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
|
||||
Future<TestProcess> update(Iterable<String> arguments) =>
|
||||
runSass(["--no-source-map", "--update"]..addAll(arguments));
|
||||
runSass(["--no-source-map", "--update", ...arguments]);
|
||||
|
||||
group("updates CSS", () {
|
||||
test("that doesn't exist yet", () async {
|
||||
|
@ -23,11 +23,8 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
|
||||
});
|
||||
|
||||
for (var poll in [true, false]) {
|
||||
Future<TestProcess> watch(Iterable<String> arguments) {
|
||||
var allArguments = ["--no-source-map", "--watch"]..addAll(arguments);
|
||||
if (poll) allArguments.add("--poll");
|
||||
return runSass(allArguments);
|
||||
}
|
||||
Future<TestProcess> watch(Iterable<String> arguments) => runSass(
|
||||
["--no-source-map", "--watch", ...arguments, if (poll) "--poll"]);
|
||||
|
||||
/// Returns a future that completes after a delay if [poll] is `true`.
|
||||
///
|
||||
|
27
test/io.dart
27
test/io.dart
@ -18,20 +18,21 @@ void ensureUpToDate(String path, String commandToRun) {
|
||||
throw "$path does not exist. Run $commandToRun.";
|
||||
}
|
||||
|
||||
var entriesToCheck = [
|
||||
...Directory("lib").listSync(recursive: true),
|
||||
|
||||
// If we have a dependency override, "pub run" will touch the lockfile to
|
||||
// mark it as newer than the pubspec, which makes it unsuitable to use for
|
||||
// freshness checking.
|
||||
if (File("pubspec.yaml")
|
||||
.readAsStringSync()
|
||||
.contains("dependency_overrides"))
|
||||
File("pubspec.yaml")
|
||||
else
|
||||
File("pubspec.lock")
|
||||
];
|
||||
|
||||
var lastModified = File(path).lastModifiedSync();
|
||||
var entriesToCheck = Directory("lib").listSync(recursive: true).toList();
|
||||
|
||||
// If we have a dependency override, "pub run" will touch the lockfile to mark
|
||||
// it as newer than the pubspec, which makes it unsuitable to use for
|
||||
// freshness checking.
|
||||
if (File("pubspec.yaml")
|
||||
.readAsStringSync()
|
||||
.contains("dependency_overrides")) {
|
||||
entriesToCheck.add(File("pubspec.yaml"));
|
||||
} else {
|
||||
entriesToCheck.add(File("pubspec.lock"));
|
||||
}
|
||||
|
||||
for (var entry in entriesToCheck) {
|
||||
if (entry is File) {
|
||||
var entryLastModified = entry.lastModifiedSync();
|
||||
|
@ -795,7 +795,7 @@ void _expectMapMatches(
|
||||
Map<String, SourceLocation> sourceLocations,
|
||||
List<Tuple2<String, SourceLocation>> targetLocations) {
|
||||
expect(sourceLocations.keys,
|
||||
equals(Set.of(targetLocations.map((tuple) => tuple.item1))));
|
||||
equals({for (var tuple in targetLocations) tuple.item1}));
|
||||
|
||||
String actualMap() =>
|
||||
"\nActual map:\n\n" + _mapToString(map, sourceText, targetText) + "\n";
|
||||
|
@ -26,10 +26,11 @@ all() {}
|
||||
|
||||
@Task('Run the Dart formatter.')
|
||||
format() {
|
||||
Pub.run('dart_style',
|
||||
script: 'format',
|
||||
arguments: ['--overwrite', '--fix']
|
||||
..addAll(existingSourceDirs.map((dir) => dir.path)));
|
||||
Pub.run('dart_style', script: 'format', arguments: [
|
||||
'--overwrite',
|
||||
'--fix',
|
||||
for (var dir in existingSourceDirs) dir.path
|
||||
]);
|
||||
}
|
||||
|
||||
@Task('Installs dependencies from npm.')
|
||||
|
@ -29,23 +29,19 @@ void _js({@required bool release}) {
|
||||
ensureBuild();
|
||||
var destination = File('build/sass.dart.js');
|
||||
|
||||
var args = [
|
||||
Dart2js.compile(File('bin/sass.dart'), outFile: destination, extraArgs: [
|
||||
'--categories=Server',
|
||||
'-Dnode=true',
|
||||
'-Dversion=$version',
|
||||
'-Ddart-version=$dartVersion',
|
||||
];
|
||||
if (release) {
|
||||
// We use O4 because:
|
||||
//
|
||||
// * We don't care about the string representation of types.
|
||||
// * We expect our test coverage to ensure that nothing throws subtypes of
|
||||
// Error.
|
||||
// * We thoroughly test edge cases in user input.
|
||||
args..add("-O4")..add("--fast-startup");
|
||||
}
|
||||
|
||||
Dart2js.compile(File('bin/sass.dart'), outFile: destination, extraArgs: args);
|
||||
if (release) ...["-O4", "--fast-startup"]
|
||||
]);
|
||||
var text = destination.readAsStringSync();
|
||||
|
||||
if (release) {
|
||||
@ -71,13 +67,15 @@ npmReleasePackage() => _npm(release: true);
|
||||
/// --trust-type-annotations. Otherwise, it compiles unminified with pessimistic
|
||||
/// type checks.
|
||||
void _npm({@required bool release}) {
|
||||
var json = jsonDecode(File('package/package.json').readAsStringSync())
|
||||
as Map<String, dynamic>;
|
||||
json['version'] = version;
|
||||
var json = {
|
||||
...(jsonDecode(File('package/package.json').readAsStringSync())
|
||||
as Map<String, dynamic>),
|
||||
"version": version
|
||||
};
|
||||
|
||||
_writeNpmPackage('build/npm', json);
|
||||
if (release) {
|
||||
_writeNpmPackage('build/npm-old', json..addAll({"name": "dart-sass"}));
|
||||
_writeNpmPackage('build/npm-old', {...json, "name": "dart-sass"});
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user