Skip to content

Commit fddf421

Browse files
authoredSep 8, 2023
Don't try to load absolute URLs from the base importer (#2077)
1 parent af0118a commit fddf421

6 files changed

+86
-7
lines changed
 

‎CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
## 1.66.2
1+
## 1.67.0
2+
3+
* **Potentially breaking bug fix**: The importer used to load a given file is no
4+
longer used to load absolute URLs that appear in that file. This was
5+
unintented behavior that contradicted the Sass specification. Absolute URLs
6+
will now correctly be loaded only from the global importer list. This applies
7+
to the modern JS API, the Dart API, and the embedded protocol.
28

39
### Embedded Sass
410

‎lib/src/async_import_cache.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ final class AsyncImportCache {
142142
throw "Custom importers are required to load stylesheets when compiling in the browser.";
143143
}
144144

145-
if (baseImporter != null) {
145+
if (baseImporter != null && url.scheme == '') {
146146
var relativeResult = await putIfAbsentAsync(_relativeCanonicalizeCache, (
147147
url,
148148
forImport: forImport,

‎lib/src/import_cache.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_import_cache.dart.
66
// See tool/grind/synchronize.dart for details.
77
//
8-
// Checksum: 1b6289e0dd362fcb02f331a16a30fe94050b4e17
8+
// Checksum: 3e4cae79c03ce2af6626b1822f1468523b401e90
99
//
1010
// ignore_for_file: unused_import
1111

@@ -142,7 +142,7 @@ final class ImportCache {
142142
throw "Custom importers are required to load stylesheets when compiling in the browser.";
143143
}
144144

145-
if (baseImporter != null) {
145+
if (baseImporter != null && url.scheme == '') {
146146
var relativeResult = _relativeCanonicalizeCache.putIfAbsent((
147147
url,
148148
forImport: forImport,

‎pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: sass
2-
version: 1.66.2-dev
2+
version: 1.67.0-dev
33
description: A Sass implementation in Dart.
44
homepage: https://github.com/sass/dart-sass
55

‎test/dart_api/importer_test.dart

+55
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,61 @@ void main() {
201201
})));
202202
});
203203

204+
group("compileString()'s importer option", () {
205+
test("loads relative imports from the entrypoint", () {
206+
var css = compileString('@import "orange";',
207+
importer: TestImporter((url) => Uri.parse("u:$url"), (url) {
208+
var color = url.path;
209+
return ImporterResult('.$color {color: $color}', indented: false);
210+
}));
211+
212+
expect(css, equals(".orange {\n color: orange;\n}"));
213+
});
214+
215+
test("loads imports relative to the entrypoint's URL", () {
216+
var css = compileString('@import "baz/qux";',
217+
importer: TestImporter((url) => url.resolve("bang"), (url) {
218+
return ImporterResult('a {result: "${url.path}"}', indented: false);
219+
}),
220+
url: Uri.parse("u:foo/bar"));
221+
222+
expect(css, equals('a {\n result: "foo/baz/bang";\n}'));
223+
});
224+
225+
test("doesn't load absolute imports", () {
226+
var css = compileString('@import "u:orange";',
227+
importer: TestImporter((_) => throw "Should not be called",
228+
(_) => throw "Should not be called"),
229+
importers: [
230+
TestImporter((url) => url, (url) {
231+
var color = url.path;
232+
return ImporterResult('.$color {color: $color}', indented: false);
233+
})
234+
]);
235+
236+
expect(css, equals(".orange {\n color: orange;\n}"));
237+
});
238+
239+
test("doesn't load from other importers", () {
240+
var css = compileString('@import "u:midstream";',
241+
importer: TestImporter((_) => throw "Should not be called",
242+
(_) => throw "Should not be called"),
243+
importers: [
244+
TestImporter((url) => url, (url) {
245+
if (url.path == "midstream") {
246+
return ImporterResult("@import 'orange';", indented: false);
247+
} else {
248+
var color = url.path;
249+
return ImporterResult('.$color {color: $color}',
250+
indented: false);
251+
}
252+
})
253+
]);
254+
255+
expect(css, equals(".orange {\n color: orange;\n}"));
256+
});
257+
});
258+
204259
group("currentLoadFromImport is", () {
205260
test("true from an @import", () {
206261
compileString('@import "foo"', importers: [FromImportImporter(true)]);

‎test/dart_api_test.dart

+20-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import 'package:test_descriptor/test_descriptor.dart' as d;
1212
import 'package:sass/sass.dart';
1313
import 'package:sass/src/exception.dart';
1414

15+
import 'dart_api/test_importer.dart';
16+
1517
void main() {
1618
// TODO(nweiz): test SASS_PATH when dart-lang/sdk#28160 is fixed.
1719

@@ -139,8 +141,9 @@ void main() {
139141
expect(css, equals("a {\n b: from-relative;\n}"));
140142
});
141143

142-
test("the original importer takes precedence over other importers",
143-
() async {
144+
test(
145+
"the original importer takes precedence over other importers for "
146+
"relative imports", () async {
144147
await d.dir(
145148
"original", [d.file("other.scss", "a {b: from-original}")]).create();
146149
await d
@@ -153,6 +156,21 @@ void main() {
153156
expect(css, equals("a {\n b: from-original;\n}"));
154157
});
155158

159+
test("importer order is preserved for absolute imports", () {
160+
var css = compileString('@import "second:other";', importers: [
161+
TestImporter((url) => url.scheme == 'first' ? url : null,
162+
(url) => ImporterResult('a {from: first}', indented: false)),
163+
// This importer should only be invoked once, because when the
164+
// "first:other" import is resolved it should be passed to the first
165+
// importer first despite being in the second importer's file.
166+
TestImporter(
167+
expectAsync1((url) => url.scheme == 'second' ? url : null,
168+
count: 1),
169+
(url) => ImporterResult('@import "first:other";', indented: false)),
170+
]);
171+
expect(css, equals("a {\n from: first;\n}"));
172+
});
173+
156174
test("importers take precedence over load paths", () async {
157175
await d.dir("load-path",
158176
[d.file("other.scss", "a {b: from-load-path}")]).create();

0 commit comments

Comments
 (0)
Please sign in to comment.