Skip to content

Commit adbfd34

Browse files
committed
fix: ensure compiler state is reset before compilation
#16268 introduced a slight regression where the state is not reset completely upon compilation. It did reset warnings but not other state, which meant if file A succeeds but file B fails in the parsing state (before the state was reset for real) it would get wrong filename info. This fixes it by setting the filename at the very beginning.
1 parent be44f8b commit adbfd34

File tree

8 files changed

+55
-29
lines changed

8 files changed

+55
-29
lines changed

.changeset/two-terms-draw.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: ensure compiler state is reset before compilation

packages/svelte/src/compiler/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export { default as preprocess } from './preprocess/index.js';
2020
*/
2121
export function compile(source, options) {
2222
source = remove_bom(source);
23-
state.reset_warnings(options.warningFilter);
23+
state.reset({ warning: options.warningFilter, filename: options.filename });
2424
const validated = validate_component_options(options, '');
2525

2626
let parsed = _parse(source);
@@ -63,7 +63,7 @@ export function compile(source, options) {
6363
*/
6464
export function compileModule(source, options) {
6565
source = remove_bom(source);
66-
state.reset_warnings(options.warningFilter);
66+
state.reset({ warning: options.warningFilter, filename: options.filename });
6767
const validated = validate_module_options(options, '');
6868

6969
const analysis = analyze_module(source, validated);
@@ -111,7 +111,7 @@ export function compileModule(source, options) {
111111
*/
112112
export function parse(source, { modern, loose } = {}) {
113113
source = remove_bom(source);
114-
state.reset_warnings(() => false);
114+
state.reset({ warning: () => false, filename: undefined });
115115

116116
const ast = _parse(source, loose);
117117
return to_public_ast(source, ast, modern);

packages/svelte/src/compiler/migrate/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { parse } from '../phases/1-parse/index.js';
99
import { regex_valid_component_name } from '../phases/1-parse/state/element.js';
1010
import { analyze_component } from '../phases/2-analyze/index.js';
1111
import { get_rune } from '../phases/scope.js';
12-
import { reset, reset_warnings } from '../state.js';
12+
import { reset, UNKNOWN_FILENAME } from '../state.js';
1313
import {
1414
extract_identifiers,
1515
extract_all_identifiers_from_expression,
@@ -134,7 +134,7 @@ export function migrate(source, { filename, use_ts } = {}) {
134134
return start + style_placeholder + end;
135135
});
136136

137-
reset_warnings(() => false);
137+
reset({ warning: () => false, filename });
138138

139139
let parsed = parse(source);
140140

@@ -145,7 +145,7 @@ export function migrate(source, { filename, use_ts } = {}) {
145145
...validate_component_options({}, ''),
146146
...parsed_options,
147147
customElementOptions,
148-
filename: filename ?? '(unknown)',
148+
filename: filename ?? UNKNOWN_FILENAME,
149149
experimental: {
150150
async: true
151151
}

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,8 @@ export function analyze_module(source, options) {
279279
classes: new Map()
280280
};
281281

282-
state.reset({
282+
state.adjust({
283283
dev: options.dev,
284-
filename: options.filename,
285284
rootDir: options.rootDir,
286285
runes: true
287286
});
@@ -531,12 +530,11 @@ export function analyze_component(root, source, options) {
531530
async_deriveds: new Set()
532531
};
533532

534-
state.reset({
533+
state.adjust({
535534
component_name: analysis.name,
536535
dev: options.dev,
537-
filename: options.filename,
538536
rootDir: options.rootDir,
539-
runes: true
537+
runes
540538
});
541539

542540
if (!runes) {

packages/svelte/src/compiler/phases/2-analyze/visitors/SvelteSelf.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { visit_component } from './shared/component.js';
44
import * as e from '../../../errors.js';
55
import * as w from '../../../warnings.js';
6-
import { filename } from '../../../state.js';
6+
import { filename, UNKNOWN_FILENAME } from '../../../state.js';
77

88
/**
99
* @param {AST.SvelteSelf} node
@@ -23,9 +23,9 @@ export function SvelteSelf(node, context) {
2323
}
2424

2525
if (context.state.analysis.runes) {
26-
const name = filename === '(unknown)' ? 'Self' : context.state.analysis.name;
26+
const name = filename === UNKNOWN_FILENAME ? 'Self' : context.state.analysis.name;
2727
const basename =
28-
filename === '(unknown)'
28+
filename === UNKNOWN_FILENAME
2929
? 'Self.svelte'
3030
: /** @type {string} */ (filename.split(/[/\\]/).pop());
3131

packages/svelte/src/compiler/state.js

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export let warnings = [];
1616
*/
1717
export let filename;
1818

19+
/**
20+
* This is the fallback used when no filename is specified.
21+
*/
22+
export const UNKNOWN_FILENAME = '(unknown)';
23+
1924
/**
2025
* The name of the component that is used in the `export default function ...` statement.
2126
*/
@@ -80,15 +85,6 @@ export function pop_ignore() {
8085
ignore_stack.pop();
8186
}
8287

83-
/**
84-
*
85-
* @param {(warning: Warning) => boolean} fn
86-
*/
87-
export function reset_warnings(fn = () => true) {
88-
warning_filter = fn;
89-
warnings = [];
90-
}
91-
9288
/**
9389
* @param {AST.SvelteNode | NodeLike} node
9490
* @param {import('../constants.js').IGNORABLE_RUNTIME_WARNINGS[number]} code
@@ -99,21 +95,36 @@ export function is_ignored(node, code) {
9995
}
10096

10197
/**
98+
* Call this to reset the compiler state. Should be called before each compilation.
99+
* @param {{ warning?: (warning: Warning) => boolean; filename: string | undefined }} state
100+
*/
101+
export function reset(state) {
102+
dev = false;
103+
runes = false;
104+
component_name = UNKNOWN_FILENAME;
105+
source = '';
106+
locator = () => undefined;
107+
filename = (state.filename ?? UNKNOWN_FILENAME).replace(/\\/g, '/');
108+
warning_filter = state.warning ?? (() => true);
109+
warnings = [];
110+
}
111+
112+
/**
113+
* Adjust the compiler state based on the provided state object.
114+
* Call this after parsing and basic analysis happened.
102115
* @param {{
103116
* dev: boolean;
104-
* filename: string;
105117
* component_name?: string;
106118
* rootDir?: string;
107119
* runes: boolean;
108120
* }} state
109121
*/
110-
export function reset(state) {
122+
export function adjust(state) {
111123
const root_dir = state.rootDir?.replace(/\\/g, '/');
112-
filename = state.filename.replace(/\\/g, '/');
113124

114125
dev = state.dev;
115126
runes = state.runes;
116-
component_name = state.component_name ?? '(unknown)';
127+
component_name = state.component_name ?? UNKNOWN_FILENAME;
117128

118129
if (typeof root_dir === 'string' && filename.startsWith(root_dir)) {
119130
// make filename relative to rootDir

packages/svelte/src/compiler/utils/compile_diagnostic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class CompileDiagnostic {
6161
this.code = code;
6262
this.message = message;
6363

64-
if (state.filename) {
64+
if (state.filename !== state.UNKNOWN_FILENAME) {
6565
this.filename = state.filename;
6666
}
6767

packages/svelte/tests/compiler-errors/test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as fs from 'node:fs';
2-
import { assert, expect } from 'vitest';
2+
import { assert, expect, it } from 'vitest';
33
import { compile, compileModule, type CompileError } from 'svelte/compiler';
44
import { suite, type BaseTest } from '../suite';
55
import { read_file } from '../helpers.js';
@@ -78,3 +78,15 @@ const { test, run } = suite<CompilerErrorTest>((config, cwd) => {
7878
export { test };
7979

8080
await run(__dirname);
81+
82+
it('resets the compiler state including filename', () => {
83+
// start with something that succeeds
84+
compile('<div>hello</div>', { filename: 'foo.svelte' });
85+
// then try something that fails in the parsing stage
86+
try {
87+
compile('<p>hello<div>invalid</p>', { filename: 'bar.svelte' });
88+
expect.fail('Expected an error');
89+
} catch (e: any) {
90+
expect(e.toString()).toContain('bar.svelte');
91+
}
92+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy