Skip to content

Commit 0ec616e

Browse files
committed
Don't use @import in the legacy importer
This unfortunately may make error reports look a little odd for errors on the first line of SCSS files loaded via the legacy importer and it'll give indented-syntax errors an off-by-one error, but there's an easy fix: stop using the legacy API. Closes #340
1 parent 40de6ec commit 0ec616e

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

lib/src/legacy/importer.ts

+29-12
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ export const endOfLoadProtocol = 'sass-embedded-legacy-load-done:';
4545
*/
4646
export const legacyImporterFileProtocol = 'legacy-importer-file:';
4747

48+
/**
49+
* A random namespace for `sas:meta`, so we can use `meta.load-css()` at the end
50+
* of the file to signal that a load has finished without polluting a namespace
51+
* a user might actually use.
52+
*/
53+
export const metaNamespace = `---${Math.random().toString(36).substring(2)}`;
54+
4855
// A count of `endOfLoadProtocol` imports that have been generated. Each one
4956
// must be a different URL to ensure that the importer results aren't cached.
5057
let endOfLoadCount = 0;
@@ -247,22 +254,20 @@ export class LegacyImporterWrapper<sync extends 'sync' | 'async'>
247254
this.lastContents ??
248255
fs.readFileSync(legacyFileUrlToPath(canonicalUrl), 'utf-8');
249256
this.lastContents = undefined;
250-
if (syntax === 'scss') {
251-
contents += this.endOfLoadImport;
252-
} else if (syntax === 'indented') {
253-
contents += `\n@import "${endOfLoadProtocol}${endOfLoadCount++}"`;
254-
} else {
257+
if (syntax === 'css') {
255258
this.prev.pop();
259+
} else {
260+
contents = this.wrapContents(contents, syntax);
256261
}
257262

258263
return {contents, syntax, sourceMapUrl: canonicalUrl};
259264
}
260265

261-
const lastContents = this.lastContents;
266+
const lastContents = this.lastContents!;
262267
assert.notEqual(lastContents, undefined);
263268
this.lastContents = undefined;
264269
return {
265-
contents: lastContents + this.endOfLoadImport,
270+
contents: this.wrapContents(lastContents, 'scss'),
266271
syntax: 'scss',
267272
sourceMapUrl: canonicalUrl,
268273
};
@@ -333,10 +338,22 @@ export class LegacyImporterWrapper<sync extends 'sync' | 'async'>
333338
}) as PromiseOr<LegacyImporterResult, sync>;
334339
}
335340

336-
// The `@import` statement to inject after the contents of files to ensure
337-
// that we know when a load has completed so we can pass the correct `prev`
338-
// argument to callbacks.
339-
private get endOfLoadImport(): string {
340-
return `\n;@import "${endOfLoadProtocol}${endOfLoadCount++}";`;
341+
// Modifies {@link contents} to ensure that we know when a load has completed
342+
// so we can pass the correct `prev` argument to callbacks.
343+
private wrapContents(contents: string, syntax: 'scss' | 'indented'): string {
344+
const url = `"${endOfLoadProtocol}${endOfLoadCount++}"`;
345+
if (syntax === 'scss') {
346+
return (
347+
`@use "sass:meta" as ${metaNamespace};` +
348+
contents +
349+
`\n;@include ${metaNamespace}.load-css(${url});`
350+
);
351+
} else {
352+
return (
353+
`@use "sass:meta" as ${metaNamespace}\n` +
354+
contents +
355+
`\n@include ${metaNamespace}.load-css(${url})`
356+
);
357+
}
341358
}
342359
}

0 commit comments

Comments
 (0)