Skip to content

Commit 470447f

Browse files
authored
Merge pull request #2217 from sass/merge-main
Merge main into feature.color-4
2 parents 62e4fa0 + 78debaa commit 470447f

30 files changed

+591
-164
lines changed

.github/util/initialize/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ runs:
3232

3333
- name: Generate Dart from protobuf
3434
run: dart run grinder protobuf
35-
env: {UPDATE_SASS_PROTOCOL: false}
35+
env: {UPDATE_SASS_SASS_REPO: false}
3636
shell: bash

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ jobs:
7070
- name: Deploy
7171
run: dart run grinder pkg-npm-deploy
7272
env:
73+
UPDATE_SASS_SASS_REPO: false
7374
NPM_TOKEN: "${{ secrets.NPM_TOKEN }}"
7475

7576
deploy_bazel:

.github/workflows/test-vendor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ jobs:
6969
- run: dart run grinder fetch-bulma
7070
env: {GITHUB_BEARER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"}
7171
- name: Build
72-
run: dart bin/sass.dart --quiet build/bulma/bulma.sass build/bulma-output.css
72+
run: dart bin/sass.dart --quiet build/bulma/bulma.scss build/bulma-output.css

.github/workflows/test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ jobs:
113113

114114
- name: Build JS
115115
run: dart run grinder pkg-npm-dev
116+
env: {UPDATE_SASS_SASS_REPO: false}
116117

117118
- name: Check out Sass specification
118119
uses: sass/clone-linked-repo@v1
@@ -203,6 +204,7 @@ jobs:
203204

204205
- name: Build JS
205206
run: dart run grinder pkg-npm-dev
207+
env: {UPDATE_SASS_SASS_REPO: false}
206208

207209
- name: Install built dependencies
208210
run: npm install
@@ -282,6 +284,7 @@ jobs:
282284
node-version: ${{ matrix.node-version }}
283285

284286
- run: dart run grinder pkg-npm-dev
287+
env: {UPDATE_SASS_SASS_REPO: false}
285288
- name: Run tests
286289
run: dart run test -t node -j 2
287290

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

305308
- run: dart run grinder pkg-npm-dev
309+
env: {UPDATE_SASS_SASS_REPO: false}
306310
- name: Run tests
307311
run: dart run test -p chrome -j 2
308312
env:

CHANGELOG.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## 1.74.0
1+
## 1.76.0
22

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

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

187+
## 1.75.0
188+
189+
* Fix a bug in which stylesheet canonicalization could be cached incorrectly
190+
when custom importers or the Node.js package importer made decisions based on
191+
the URL of the containing stylesheet.
192+
193+
### JS API
194+
195+
* Allow `importer` to be passed without `url` in `StringOptionsWithImporter`.
196+
197+
## 1.74.1
198+
199+
* No user-visible changes.
200+
201+
## 1.74.0
202+
203+
### JS API
204+
205+
* Add a new top-level `deprecations` object, which contains various
206+
`Deprecation` objects that define the different types of deprecation used by
207+
the Sass compiler and can be passed to the options below.
208+
209+
* Add a new `fatalDeprecations` compiler option that causes the compiler to
210+
error if any deprecation warnings of the provided types are encountered. You
211+
can also pass in a `Version` object to treat all deprecations that were active
212+
in that Dart Sass version as fatal.
213+
214+
* Add a new `futureDeprecations` compiler option that allows you to opt-in to
215+
certain deprecations early (currently just `import`).
216+
217+
* Add a new `silenceDeprecations` compiler option to ignore any deprecation
218+
warnings of the provided types.
219+
220+
### Command-Line Interface
221+
222+
* Add a new `--silence-deprecation` flag, which causes the compiler to ignore
223+
any deprecation warnings of the provided types.
224+
225+
* Previously, if a future deprecation was passed to `--fatal-deprecation` but
226+
not `--future-deprecation`, it would be treated as fatal despite not being
227+
enabled. Both flags are now required to treat a future deprecation as fatal
228+
with a warning emitted if `--fatal-deprecation` is passed without
229+
`--future-deprecation`, matching the JS API's behavior.
230+
231+
### Dart API
232+
233+
* The `compile` methods now take in a `silenceDeprecations` parameter, which
234+
causes the compiler to ignore any deprecation warnings of the provided types.
235+
236+
* Add `Deprecation.obsoleteIn` to match the JS API. This is currently null for
237+
all deprecations, but will be used once some deprecations become obsolete in
238+
Dart Sass 2.0.0.
239+
240+
* **Potentially breaking bug fix:** Fix a bug where `compileStringToResultAsync`
241+
ignored `fatalDeprecations` and `futureDeprecations`.
242+
243+
* The behavior around making future deprecations fatal mentioned in the CLI
244+
section above has also been changed in the Dart API.
245+
187246
## 1.73.0
188247

189248
* Add support for nesting in plain CSS files. This is not processed by Sass at

bin/sass.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import 'package:sass/src/executable/watch.dart';
1515
import 'package:sass/src/import_cache.dart';
1616
import 'package:sass/src/importer/filesystem.dart';
1717
import 'package:sass/src/io.dart';
18-
import 'package:sass/src/logger/deprecation_handling.dart';
18+
import 'package:sass/src/logger/deprecation_processing.dart';
1919
import 'package:sass/src/stylesheet_graph.dart';
2020
import 'package:sass/src/utils.dart';
2121
import 'package:sass/src/embedded/executable.dart'
@@ -53,7 +53,8 @@ Future<void> main(List<String> args) async {
5353
// limit repetition. A separate DeprecationHandlingLogger is created for
5454
// each compilation, which will limit repetition if verbose is not
5555
// passed in addition to handling fatal/future deprecations.
56-
logger: DeprecationHandlingLogger(options.logger,
56+
logger: DeprecationProcessingLogger(options.logger,
57+
silenceDeprecations: options.silenceDeprecations,
5758
fatalDeprecations: options.fatalDeprecations,
5859
futureDeprecations: options.futureDeprecations,
5960
limitRepetition: false)));

lib/sass.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ CompileResult compileToResult(String path,
113113
bool verbose = false,
114114
bool sourceMap = false,
115115
bool charset = true,
116+
Iterable<Deprecation>? silenceDeprecations,
116117
Iterable<Deprecation>? fatalDeprecations,
117118
Iterable<Deprecation>? futureDeprecations}) =>
118119
c.compile(path,
@@ -128,6 +129,7 @@ CompileResult compileToResult(String path,
128129
verbose: verbose,
129130
sourceMap: sourceMap,
130131
charset: charset,
132+
silenceDeprecations: silenceDeprecations,
131133
fatalDeprecations: fatalDeprecations,
132134
futureDeprecations: futureDeprecations);
133135

@@ -212,6 +214,7 @@ CompileResult compileStringToResult(String source,
212214
bool verbose = false,
213215
bool sourceMap = false,
214216
bool charset = true,
217+
Iterable<Deprecation>? silenceDeprecations,
215218
Iterable<Deprecation>? fatalDeprecations,
216219
Iterable<Deprecation>? futureDeprecations}) =>
217220
c.compileString(source,
@@ -230,6 +233,7 @@ CompileResult compileStringToResult(String source,
230233
verbose: verbose,
231234
sourceMap: sourceMap,
232235
charset: charset,
236+
silenceDeprecations: silenceDeprecations,
233237
fatalDeprecations: fatalDeprecations,
234238
futureDeprecations: futureDeprecations);
235239

@@ -250,6 +254,7 @@ Future<CompileResult> compileToResultAsync(String path,
250254
bool verbose = false,
251255
bool sourceMap = false,
252256
bool charset = true,
257+
Iterable<Deprecation>? silenceDeprecations,
253258
Iterable<Deprecation>? fatalDeprecations,
254259
Iterable<Deprecation>? futureDeprecations}) =>
255260
c.compileAsync(path,
@@ -265,6 +270,7 @@ Future<CompileResult> compileToResultAsync(String path,
265270
verbose: verbose,
266271
sourceMap: sourceMap,
267272
charset: charset,
273+
silenceDeprecations: silenceDeprecations,
268274
fatalDeprecations: fatalDeprecations,
269275
futureDeprecations: futureDeprecations);
270276

@@ -290,6 +296,7 @@ Future<CompileResult> compileStringToResultAsync(String source,
290296
bool verbose = false,
291297
bool sourceMap = false,
292298
bool charset = true,
299+
Iterable<Deprecation>? silenceDeprecations,
293300
Iterable<Deprecation>? fatalDeprecations,
294301
Iterable<Deprecation>? futureDeprecations}) =>
295302
c.compileStringAsync(source,
@@ -307,7 +314,10 @@ Future<CompileResult> compileStringToResultAsync(String source,
307314
quietDeps: quietDeps,
308315
verbose: verbose,
309316
sourceMap: sourceMap,
310-
charset: charset);
317+
charset: charset,
318+
silenceDeprecations: silenceDeprecations,
319+
fatalDeprecations: fatalDeprecations,
320+
futureDeprecations: futureDeprecations);
311321

312322
/// Like [compileToResult], but returns [CompileResult.css] rather than
313323
/// returning [CompileResult] directly.

lib/src/async_compile.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import 'importer/legacy_node.dart';
1717
import 'importer/no_op.dart';
1818
import 'io.dart';
1919
import 'logger.dart';
20-
import 'logger/deprecation_handling.dart';
20+
import 'logger/deprecation_processing.dart';
2121
import 'syntax.dart';
2222
import 'utils.dart';
2323
import 'visitor/async_evaluate.dart';
@@ -42,10 +42,12 @@ Future<CompileResult> compileAsync(String path,
4242
bool verbose = false,
4343
bool sourceMap = false,
4444
bool charset = true,
45+
Iterable<Deprecation>? silenceDeprecations,
4546
Iterable<Deprecation>? fatalDeprecations,
4647
Iterable<Deprecation>? futureDeprecations}) async {
47-
DeprecationHandlingLogger deprecationLogger = logger =
48-
DeprecationHandlingLogger(logger ?? Logger.stderr(),
48+
DeprecationProcessingLogger deprecationLogger = logger =
49+
DeprecationProcessingLogger(logger ?? Logger.stderr(),
50+
silenceDeprecations: {...?silenceDeprecations},
4951
fatalDeprecations: {...?fatalDeprecations},
5052
futureDeprecations: {...?futureDeprecations},
5153
limitRepetition: !verbose);
@@ -106,10 +108,12 @@ Future<CompileResult> compileStringAsync(String source,
106108
bool verbose = false,
107109
bool sourceMap = false,
108110
bool charset = true,
111+
Iterable<Deprecation>? silenceDeprecations,
109112
Iterable<Deprecation>? fatalDeprecations,
110113
Iterable<Deprecation>? futureDeprecations}) async {
111-
DeprecationHandlingLogger deprecationLogger = logger =
112-
DeprecationHandlingLogger(logger ?? Logger.stderr(),
114+
DeprecationProcessingLogger deprecationLogger = logger =
115+
DeprecationProcessingLogger(logger ?? Logger.stderr(),
116+
silenceDeprecations: {...?silenceDeprecations},
113117
fatalDeprecations: {...?fatalDeprecations},
114118
futureDeprecations: {...?futureDeprecations},
115119
limitRepetition: !verbose);

lib/src/async_import_cache.dart

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -154,64 +154,85 @@ final class AsyncImportCache {
154154
}
155155

156156
if (baseImporter != null && url.scheme == '') {
157-
var relativeResult = await putIfAbsentAsync(
158-
_relativeCanonicalizeCache,
159-
(
160-
url,
161-
forImport: forImport,
162-
baseImporter: baseImporter,
163-
baseUrl: baseUrl
164-
),
165-
() => _canonicalize(baseImporter, baseUrl?.resolveUri(url) ?? url,
166-
baseUrl, forImport));
157+
var relativeResult = await putIfAbsentAsync(_relativeCanonicalizeCache, (
158+
url,
159+
forImport: forImport,
160+
baseImporter: baseImporter,
161+
baseUrl: baseUrl
162+
), () async {
163+
var (result, cacheable) = await _canonicalize(
164+
baseImporter, baseUrl?.resolveUri(url) ?? url, baseUrl, forImport);
165+
assert(
166+
cacheable,
167+
"Relative loads should always be cacheable because they never "
168+
"provide access to the containing URL.");
169+
return result;
170+
});
167171
if (relativeResult != null) return relativeResult;
168172
}
169173

170-
return await putIfAbsentAsync(
171-
_canonicalizeCache, (url, forImport: forImport), () async {
172-
for (var importer in _importers) {
173-
if (await _canonicalize(importer, url, baseUrl, forImport)
174-
case var result?) {
174+
var key = (url, forImport: forImport);
175+
if (_canonicalizeCache.containsKey(key)) return _canonicalizeCache[key];
176+
177+
// Each indivudal call to a `canonicalize()` override may not be cacheable
178+
// (specifically, if it has access to `containingUrl` it's too
179+
// context-sensitive to usefully cache). We want to cache a given URL across
180+
// the _entire_ importer chain, so we use [cacheable] to track whether _all_
181+
// `canonicalize()` calls we've attempted are cacheable. Only if they are do
182+
// we store the result in the cache.
183+
var cacheable = true;
184+
for (var importer in _importers) {
185+
switch (await _canonicalize(importer, url, baseUrl, forImport)) {
186+
case (var result?, true) when cacheable:
187+
_canonicalizeCache[key] = result;
188+
return result;
189+
190+
case (var result?, _):
175191
return result;
176-
}
192+
193+
case (_, false):
194+
cacheable = false;
177195
}
196+
}
178197

179-
return null;
180-
});
198+
if (cacheable) _canonicalizeCache[key] = null;
199+
return null;
181200
}
182201

183202
/// Calls [importer.canonicalize] and prints a deprecation warning if it
184203
/// returns a relative URL.
185204
///
186-
/// If [resolveUrl] is `true`, this resolves [url] relative to [baseUrl]
187-
/// before passing it to [importer].
188-
Future<AsyncCanonicalizeResult?> _canonicalize(
189-
AsyncImporter importer, Uri url, Uri? baseUrl, bool forImport,
190-
{bool resolveUrl = false}) async {
191-
var resolved =
192-
resolveUrl && baseUrl != null ? baseUrl.resolveUri(url) : url;
205+
/// This returns both the result of the call to `canonicalize()` and whether
206+
/// that result is cacheable at all.
207+
Future<(AsyncCanonicalizeResult?, bool cacheable)> _canonicalize(
208+
AsyncImporter importer, Uri url, Uri? baseUrl, bool forImport) async {
193209
var canonicalize = forImport
194-
? () => inImportRule(() => importer.canonicalize(resolved))
195-
: () => importer.canonicalize(resolved);
210+
? () => inImportRule(() => importer.canonicalize(url))
211+
: () => importer.canonicalize(url);
196212

197213
var passContainingUrl = baseUrl != null &&
198214
(url.scheme == '' || await importer.isNonCanonicalScheme(url.scheme));
199215
var result = await withContainingUrl(
200216
passContainingUrl ? baseUrl : null, canonicalize);
201-
if (result == null) return null;
217+
218+
// TODO(sass/dart-sass#2208): Determine whether the containing URL was
219+
// _actually_ accessed rather than assuming it was.
220+
var cacheable = !passContainingUrl || importer is FilesystemImporter;
221+
222+
if (result == null) return (null, cacheable);
202223

203224
if (result.scheme == '') {
204225
_logger.warnForDeprecation(
205226
Deprecation.relativeCanonical,
206-
"Importer $importer canonicalized $resolved to $result.\n"
227+
"Importer $importer canonicalized $url to $result.\n"
207228
"Relative canonical URLs are deprecated and will eventually be "
208229
"disallowed.");
209230
} else if (await importer.isNonCanonicalScheme(result.scheme)) {
210-
throw "Importer $importer canonicalized $resolved to $result, which "
211-
"uses a scheme declared as non-canonical.";
231+
throw "Importer $importer canonicalized $url to $result, which uses a "
232+
"scheme declared as non-canonical.";
212233
}
213234

214-
return (importer, result, originalUrl: resolved);
235+
return ((importer, result, originalUrl: url), cacheable);
215236
}
216237

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

0 commit comments

Comments
 (0)