Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge main into feature.color-4 #2217

Merged
merged 7 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/util/initialize/action.yml
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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