Skip to content

Commit

Permalink
Don't use @import in the legacy importer (#342)
Browse files Browse the repository at this point in the history
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

Co-authored-by: Jennifer Thakar <[email protected]>
  • Loading branch information
nex3 and jathak authored Oct 29, 2024
1 parent 6d60eea commit 80e2b88
Showing 1 changed file with 29 additions and 12 deletions.
41 changes: 29 additions & 12 deletions lib/src/legacy/importer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ export const endOfLoadProtocol = 'sass-embedded-legacy-load-done:';
*/
export const legacyImporterFileProtocol = 'legacy-importer-file:';

/**
* A random namespace for `sass:meta`, so we can use `meta.load-css()` at the end
* of the file to signal that a load has finished without polluting a namespace
* a user might actually use.
*/
export const metaNamespace = `---${Math.random().toString(36).substring(2)}`;

// A count of `endOfLoadProtocol` imports that have been generated. Each one
// must be a different URL to ensure that the importer results aren't cached.
let endOfLoadCount = 0;
Expand Down Expand Up @@ -247,22 +254,20 @@ export class LegacyImporterWrapper<sync extends 'sync' | 'async'>
this.lastContents ??
fs.readFileSync(legacyFileUrlToPath(canonicalUrl), 'utf-8');
this.lastContents = undefined;
if (syntax === 'scss') {
contents += this.endOfLoadImport;
} else if (syntax === 'indented') {
contents += `\n@import "${endOfLoadProtocol}${endOfLoadCount++}"`;
} else {
if (syntax === 'css') {
this.prev.pop();
} else {
contents = this.wrapContents(contents, syntax);
}

return {contents, syntax, sourceMapUrl: canonicalUrl};
}

const lastContents = this.lastContents;
const lastContents = this.lastContents!;
assert.notEqual(lastContents, undefined);
this.lastContents = undefined;
return {
contents: lastContents + this.endOfLoadImport,
contents: this.wrapContents(lastContents, 'scss'),
syntax: 'scss',
sourceMapUrl: canonicalUrl,
};
Expand Down Expand Up @@ -333,10 +338,22 @@ export class LegacyImporterWrapper<sync extends 'sync' | 'async'>
}) as PromiseOr<LegacyImporterResult, sync>;
}

// The `@import` statement to inject after the contents of files to ensure
// that we know when a load has completed so we can pass the correct `prev`
// argument to callbacks.
private get endOfLoadImport(): string {
return `\n;@import "${endOfLoadProtocol}${endOfLoadCount++}";`;
// Modifies {@link contents} to ensure that we know when a load has completed
// so we can pass the correct `prev` argument to callbacks.
private wrapContents(contents: string, syntax: 'scss' | 'indented'): string {
const url = `"${endOfLoadProtocol}${endOfLoadCount++}"`;
if (syntax === 'scss') {
return (
`@use "sass:meta" as ${metaNamespace};` +
contents +
`\n;@include ${metaNamespace}.load-css(${url});`
);
} else {
return (
`@use "sass:meta" as ${metaNamespace}\n` +
contents +
`\n@include ${metaNamespace}.load-css(${url})`
);
}
}
}

0 comments on commit 80e2b88

Please sign in to comment.