Skip to content

Commit

Permalink
Merge pull request #2217 from sass/merge-main
Browse files Browse the repository at this point in the history
Merge main into feature.color-4
  • Loading branch information
nex3 committed Apr 12, 2024
2 parents 62e4fa0 + 78debaa commit 470447f
Show file tree
Hide file tree
Showing 30 changed files with 591 additions and 164 deletions.
2 changes: 1 addition & 1 deletion .github/util/initialize/action.yml
Expand Up @@ -32,5 +32,5 @@ runs:

- name: Generate Dart from protobuf
run: dart run grinder protobuf
env: {UPDATE_SASS_PROTOCOL: false}
env: {UPDATE_SASS_SASS_REPO: false}
shell: bash
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Expand Up @@ -70,6 +70,7 @@ jobs:
- name: Deploy
run: dart run grinder pkg-npm-deploy
env:
UPDATE_SASS_SASS_REPO: false
NPM_TOKEN: "${{ secrets.NPM_TOKEN }}"

deploy_bazel:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-vendor.yml
Expand Up @@ -69,4 +69,4 @@ jobs:
- run: dart run grinder fetch-bulma
env: {GITHUB_BEARER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"}
- name: Build
run: dart bin/sass.dart --quiet build/bulma/bulma.sass build/bulma-output.css
run: dart bin/sass.dart --quiet build/bulma/bulma.scss build/bulma-output.css
4 changes: 4 additions & 0 deletions .github/workflows/test.yml
Expand Up @@ -113,6 +113,7 @@ jobs:

- name: Build JS
run: dart run grinder pkg-npm-dev
env: {UPDATE_SASS_SASS_REPO: false}

- name: Check out Sass specification
uses: sass/clone-linked-repo@v1
Expand Down Expand Up @@ -203,6 +204,7 @@ jobs:

- name: Build JS
run: dart run grinder pkg-npm-dev
env: {UPDATE_SASS_SASS_REPO: false}

- name: Install built dependencies
run: npm install
Expand Down Expand Up @@ -282,6 +284,7 @@ jobs:
node-version: ${{ matrix.node-version }}

- run: dart run grinder pkg-npm-dev
env: {UPDATE_SASS_SASS_REPO: false}
- name: Run tests
run: dart run test -t node -j 2

Expand All @@ -303,6 +306,7 @@ jobs:
github-token: ${{ github.token }}

- run: dart run grinder pkg-npm-dev
env: {UPDATE_SASS_SASS_REPO: false}
- name: Run tests
run: dart run test -p chrome -j 2
env:
Expand Down
61 changes: 60 additions & 1 deletion CHANGELOG.md
@@ -1,4 +1,4 @@
## 1.74.0
## 1.76.0

* **Breaking change**: Passing a number with unit `%` to the `$alpha` parameter
of `color.change()`, `color.adjust()`, `change-color()`, and `adjust-color()`
Expand Down Expand Up @@ -184,6 +184,65 @@

* Remove `RgbColor`, `HslColor` and `HwbColor` SassScript values.

## 1.75.0

* Fix a bug in which stylesheet canonicalization could be cached incorrectly
when custom importers or the Node.js package importer made decisions based on
the URL of the containing stylesheet.

### JS API

* Allow `importer` to be passed without `url` in `StringOptionsWithImporter`.

## 1.74.1

* No user-visible changes.

## 1.74.0

### JS API

* Add a new top-level `deprecations` object, which contains various
`Deprecation` objects that define the different types of deprecation used by
the Sass compiler and can be passed to the options below.

* Add a new `fatalDeprecations` compiler option that causes the compiler to
error if any deprecation warnings of the provided types are encountered. You
can also pass in a `Version` object to treat all deprecations that were active
in that Dart Sass version as fatal.

* Add a new `futureDeprecations` compiler option that allows you to opt-in to
certain deprecations early (currently just `import`).

* Add a new `silenceDeprecations` compiler option to ignore any deprecation
warnings of the provided types.

### Command-Line Interface

* Add a new `--silence-deprecation` flag, which causes the compiler to ignore
any deprecation warnings of the provided types.

* Previously, if a future deprecation was passed to `--fatal-deprecation` but
not `--future-deprecation`, it would be treated as fatal despite not being
enabled. Both flags are now required to treat a future deprecation as fatal
with a warning emitted if `--fatal-deprecation` is passed without
`--future-deprecation`, matching the JS API's behavior.

### Dart API

* The `compile` methods now take in a `silenceDeprecations` parameter, which
causes the compiler to ignore any deprecation warnings of the provided types.

* Add `Deprecation.obsoleteIn` to match the JS API. This is currently null for
all deprecations, but will be used once some deprecations become obsolete in
Dart Sass 2.0.0.

* **Potentially breaking bug fix:** Fix a bug where `compileStringToResultAsync`
ignored `fatalDeprecations` and `futureDeprecations`.

* The behavior around making future deprecations fatal mentioned in the CLI
section above has also been changed in the Dart API.

## 1.73.0

* Add support for nesting in plain CSS files. This is not processed by Sass at
Expand Down
5 changes: 3 additions & 2 deletions bin/sass.dart
Expand Up @@ -15,7 +15,7 @@ import 'package:sass/src/executable/watch.dart';
import 'package:sass/src/import_cache.dart';
import 'package:sass/src/importer/filesystem.dart';
import 'package:sass/src/io.dart';
import 'package:sass/src/logger/deprecation_handling.dart';
import 'package:sass/src/logger/deprecation_processing.dart';
import 'package:sass/src/stylesheet_graph.dart';
import 'package:sass/src/utils.dart';
import 'package:sass/src/embedded/executable.dart'
Expand Down Expand Up @@ -53,7 +53,8 @@ Future<void> main(List<String> args) async {
// limit repetition. A separate DeprecationHandlingLogger is created for
// each compilation, which will limit repetition if verbose is not
// passed in addition to handling fatal/future deprecations.
logger: DeprecationHandlingLogger(options.logger,
logger: DeprecationProcessingLogger(options.logger,
silenceDeprecations: options.silenceDeprecations,
fatalDeprecations: options.fatalDeprecations,
futureDeprecations: options.futureDeprecations,
limitRepetition: false)));
Expand Down
12 changes: 11 additions & 1 deletion lib/sass.dart
Expand Up @@ -113,6 +113,7 @@ CompileResult compileToResult(String path,
bool verbose = false,
bool sourceMap = false,
bool charset = true,
Iterable<Deprecation>? silenceDeprecations,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compile(path,
Expand All @@ -128,6 +129,7 @@ CompileResult compileToResult(String path,
verbose: verbose,
sourceMap: sourceMap,
charset: charset,
silenceDeprecations: silenceDeprecations,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

Expand Down Expand Up @@ -212,6 +214,7 @@ CompileResult compileStringToResult(String source,
bool verbose = false,
bool sourceMap = false,
bool charset = true,
Iterable<Deprecation>? silenceDeprecations,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compileString(source,
Expand All @@ -230,6 +233,7 @@ CompileResult compileStringToResult(String source,
verbose: verbose,
sourceMap: sourceMap,
charset: charset,
silenceDeprecations: silenceDeprecations,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

Expand All @@ -250,6 +254,7 @@ Future<CompileResult> compileToResultAsync(String path,
bool verbose = false,
bool sourceMap = false,
bool charset = true,
Iterable<Deprecation>? silenceDeprecations,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compileAsync(path,
Expand All @@ -265,6 +270,7 @@ Future<CompileResult> compileToResultAsync(String path,
verbose: verbose,
sourceMap: sourceMap,
charset: charset,
silenceDeprecations: silenceDeprecations,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

Expand All @@ -290,6 +296,7 @@ Future<CompileResult> compileStringToResultAsync(String source,
bool verbose = false,
bool sourceMap = false,
bool charset = true,
Iterable<Deprecation>? silenceDeprecations,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) =>
c.compileStringAsync(source,
Expand All @@ -307,7 +314,10 @@ Future<CompileResult> compileStringToResultAsync(String source,
quietDeps: quietDeps,
verbose: verbose,
sourceMap: sourceMap,
charset: charset);
charset: charset,
silenceDeprecations: silenceDeprecations,
fatalDeprecations: fatalDeprecations,
futureDeprecations: futureDeprecations);

/// Like [compileToResult], but returns [CompileResult.css] rather than
/// returning [CompileResult] directly.
Expand Down
14 changes: 9 additions & 5 deletions lib/src/async_compile.dart
Expand Up @@ -17,7 +17,7 @@ import 'importer/legacy_node.dart';
import 'importer/no_op.dart';
import 'io.dart';
import 'logger.dart';
import 'logger/deprecation_handling.dart';
import 'logger/deprecation_processing.dart';
import 'syntax.dart';
import 'utils.dart';
import 'visitor/async_evaluate.dart';
Expand All @@ -42,10 +42,12 @@ Future<CompileResult> compileAsync(String path,
bool verbose = false,
bool sourceMap = false,
bool charset = true,
Iterable<Deprecation>? silenceDeprecations,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) async {
DeprecationHandlingLogger deprecationLogger = logger =
DeprecationHandlingLogger(logger ?? Logger.stderr(),
DeprecationProcessingLogger deprecationLogger = logger =
DeprecationProcessingLogger(logger ?? Logger.stderr(),
silenceDeprecations: {...?silenceDeprecations},
fatalDeprecations: {...?fatalDeprecations},
futureDeprecations: {...?futureDeprecations},
limitRepetition: !verbose);
Expand Down Expand Up @@ -106,10 +108,12 @@ Future<CompileResult> compileStringAsync(String source,
bool verbose = false,
bool sourceMap = false,
bool charset = true,
Iterable<Deprecation>? silenceDeprecations,
Iterable<Deprecation>? fatalDeprecations,
Iterable<Deprecation>? futureDeprecations}) async {
DeprecationHandlingLogger deprecationLogger = logger =
DeprecationHandlingLogger(logger ?? Logger.stderr(),
DeprecationProcessingLogger deprecationLogger = logger =
DeprecationProcessingLogger(logger ?? Logger.stderr(),
silenceDeprecations: {...?silenceDeprecations},
fatalDeprecations: {...?fatalDeprecations},
futureDeprecations: {...?futureDeprecations},
limitRepetition: !verbose);
Expand Down
85 changes: 53 additions & 32 deletions lib/src/async_import_cache.dart
Expand Up @@ -154,64 +154,85 @@ final class AsyncImportCache {
}

if (baseImporter != null && url.scheme == '') {
var relativeResult = await putIfAbsentAsync(
_relativeCanonicalizeCache,
(
url,
forImport: forImport,
baseImporter: baseImporter,
baseUrl: baseUrl
),
() => _canonicalize(baseImporter, baseUrl?.resolveUri(url) ?? url,
baseUrl, forImport));
var relativeResult = await putIfAbsentAsync(_relativeCanonicalizeCache, (
url,
forImport: forImport,
baseImporter: baseImporter,
baseUrl: baseUrl
), () async {
var (result, cacheable) = await _canonicalize(
baseImporter, baseUrl?.resolveUri(url) ?? url, baseUrl, forImport);
assert(
cacheable,
"Relative loads should always be cacheable because they never "
"provide access to the containing URL.");
return result;
});
if (relativeResult != null) return relativeResult;
}

return await putIfAbsentAsync(
_canonicalizeCache, (url, forImport: forImport), () async {
for (var importer in _importers) {
if (await _canonicalize(importer, url, baseUrl, forImport)
case var result?) {
var key = (url, forImport: forImport);
if (_canonicalizeCache.containsKey(key)) return _canonicalizeCache[key];

// Each indivudal call to a `canonicalize()` override may not be cacheable
// (specifically, if it has access to `containingUrl` it's too
// context-sensitive to usefully cache). We want to cache a given URL across
// the _entire_ importer chain, so we use [cacheable] to track whether _all_
// `canonicalize()` calls we've attempted are cacheable. Only if they are do
// we store the result in the cache.
var cacheable = true;
for (var importer in _importers) {
switch (await _canonicalize(importer, url, baseUrl, forImport)) {
case (var result?, true) when cacheable:
_canonicalizeCache[key] = result;
return result;

case (var result?, _):
return result;
}

case (_, false):
cacheable = false;
}
}

return null;
});
if (cacheable) _canonicalizeCache[key] = null;
return null;
}

/// Calls [importer.canonicalize] and prints a deprecation warning if it
/// returns a relative URL.
///
/// If [resolveUrl] is `true`, this resolves [url] relative to [baseUrl]
/// before passing it to [importer].
Future<AsyncCanonicalizeResult?> _canonicalize(
AsyncImporter importer, Uri url, Uri? baseUrl, bool forImport,
{bool resolveUrl = false}) async {
var resolved =
resolveUrl && baseUrl != null ? baseUrl.resolveUri(url) : url;
/// This returns both the result of the call to `canonicalize()` and whether
/// that result is cacheable at all.
Future<(AsyncCanonicalizeResult?, bool cacheable)> _canonicalize(
AsyncImporter importer, Uri url, Uri? baseUrl, bool forImport) async {
var canonicalize = forImport
? () => inImportRule(() => importer.canonicalize(resolved))
: () => importer.canonicalize(resolved);
? () => inImportRule(() => importer.canonicalize(url))
: () => importer.canonicalize(url);

var passContainingUrl = baseUrl != null &&
(url.scheme == '' || await importer.isNonCanonicalScheme(url.scheme));
var result = await withContainingUrl(
passContainingUrl ? baseUrl : null, canonicalize);
if (result == null) return null;

// TODO(sass/dart-sass#2208): Determine whether the containing URL was
// _actually_ accessed rather than assuming it was.
var cacheable = !passContainingUrl || importer is FilesystemImporter;

if (result == null) return (null, cacheable);

if (result.scheme == '') {
_logger.warnForDeprecation(
Deprecation.relativeCanonical,
"Importer $importer canonicalized $resolved to $result.\n"
"Importer $importer canonicalized $url to $result.\n"
"Relative canonical URLs are deprecated and will eventually be "
"disallowed.");
} else if (await importer.isNonCanonicalScheme(result.scheme)) {
throw "Importer $importer canonicalized $resolved to $result, which "
"uses a scheme declared as non-canonical.";
throw "Importer $importer canonicalized $url to $result, which uses a "
"scheme declared as non-canonical.";
}

return (importer, result, originalUrl: resolved);
return ((importer, result, originalUrl: url), cacheable);
}

/// Tries to import [url] using one of this cache's importers.
Expand Down

0 comments on commit 470447f

Please sign in to comment.