Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions packages/svelte/src/compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ export { default as preprocess } from './preprocess/index.js';
*/
export function compile(source, options) {
source = remove_bom(source);
state.reset_warning_filter(options.warningFilter);
state.reset_warnings(options.warningFilter);
const validated = validate_component_options(options, '');
state.reset(source, validated);

let parsed = _parse(source);

Expand Down Expand Up @@ -64,9 +63,8 @@ export function compile(source, options) {
*/
export function compileModule(source, options) {
source = remove_bom(source);
state.reset_warning_filter(options.warningFilter);
state.reset_warnings(options.warningFilter);
const validated = validate_module_options(options, '');
state.reset(source, validated);

const analysis = analyze_module(source, validated);
return transform_module(analysis, source, validated);
Expand Down Expand Up @@ -96,6 +94,7 @@ export function compileModule(source, options) {
* @returns {Record<string, any>}
*/

// TODO 6.0 remove unused `filename`
/**
* The parse function parses a component, returning only its abstract syntax tree.
*
Expand All @@ -104,14 +103,15 @@ export function compileModule(source, options) {
*
* The `loose` option, available since 5.13.0, tries to always return an AST even if the input will not successfully compile.
*
* The `filename` option is unused and will be removed in Svelte 6.0.
*
* @param {string} source
* @param {{ filename?: string; rootDir?: string; modern?: boolean; loose?: boolean }} [options]
* @returns {AST.Root | LegacyRoot}
*/
export function parse(source, { filename, rootDir, modern, loose } = {}) {
export function parse(source, { modern, loose } = {}) {
source = remove_bom(source);
state.reset_warning_filter(() => false);
state.reset(source, { filename: filename ?? '(unknown)', rootDir });
state.reset_warnings(() => false);

const ast = _parse(source, loose);
return to_public_ast(source, ast, modern);
Expand Down
5 changes: 2 additions & 3 deletions packages/svelte/src/compiler/migrate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { parse } from '../phases/1-parse/index.js';
import { regex_valid_component_name } from '../phases/1-parse/state/element.js';
import { analyze_component } from '../phases/2-analyze/index.js';
import { get_rune } from '../phases/scope.js';
import { reset, reset_warning_filter } from '../state.js';
import { reset, reset_warnings } from '../state.js';
import {
extract_identifiers,
extract_all_identifiers_from_expression,
Expand Down Expand Up @@ -134,8 +134,7 @@ export function migrate(source, { filename, use_ts } = {}) {
return start + style_placeholder + end;
});

reset_warning_filter(() => false);
reset(source, { filename: filename ?? '(unknown)' });
reset_warnings(() => false);

let parsed = parse(source);

Expand Down
3 changes: 3 additions & 0 deletions packages/svelte/src/compiler/phases/1-parse/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { create_fragment } from './utils/create.js';
import read_options from './read/options.js';
import { is_reserved } from '../../../utils.js';
import { disallow_children } from '../2-analyze/visitors/shared/special-element.js';
import * as state from '../../state.js';

const regex_position_indicator = / \(\d+:\d+\)$/;

Expand Down Expand Up @@ -301,6 +302,8 @@ export class Parser {
* @returns {AST.Root}
*/
export function parse(template, loose = false) {
state.set_source(template);

const parser = new Parser(template, loose);
return parser.root;
}
Expand Down
17 changes: 17 additions & 0 deletions packages/svelte/src/compiler/phases/2-analyze/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import { UseDirective } from './visitors/UseDirective.js';
import { VariableDeclarator } from './visitors/VariableDeclarator.js';
import is_reference from 'is-reference';
import { mark_subtree_dynamic } from './visitors/shared/fragment.js';
import * as state from '../../state.js';

/**
* @type {Visitors}
Expand Down Expand Up @@ -240,6 +241,7 @@ export function analyze_module(source, options) {
/** @type {AST.JSComment[]} */
const comments = [];

state.set_source(source);
const ast = parse(source, comments, false, false);

const { scope, scopes } = create_scopes(ast, new ScopeRoot(), false, null);
Expand Down Expand Up @@ -269,6 +271,13 @@ export function analyze_module(source, options) {
classes: new Map()
};

state.reset({
dev: options.dev,
filename: options.filename,
rootDir: options.rootDir,
runes: true
});

walk(
/** @type {Node} */ (ast),
{
Expand Down Expand Up @@ -506,6 +515,14 @@ export function analyze_component(root, source, options) {
snippets: new Set()
};

state.reset({
component_name: analysis.name,
dev: options.dev,
filename: options.filename,
rootDir: options.rootDir,
runes: true
});

if (!runes) {
// every exported `let` or `var` declaration becomes a prop, everything else becomes an export
for (const node of instance.ast.body) {
Expand Down
3 changes: 3 additions & 0 deletions packages/svelte/src/compiler/phases/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export interface ReactiveStatement {
*/
export interface Analysis {
module: Js;
/** @deprecated use `component_name` from `state.js` instead */
name: string; // TODO should this be filename? it's used in `compileModule` as well as `compile`
/** @deprecated use `runes` from `state.js` instead */
runes: boolean;
immutable: boolean;
tracing: boolean;
Expand Down Expand Up @@ -90,6 +92,7 @@ export interface ComponentAnalysis extends Analysis {
keyframes: string[];
has_global: boolean;
};
/** @deprecated use `source` from `state.js` instead */
source: string;
undefined_exports: Map<string, Node>;
/**
Expand Down
35 changes: 25 additions & 10 deletions packages/svelte/src/compiler/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export let warnings = [];
*/
export let filename;

export let component_name = '<unknown>';

/**
* The original source code
* @type {string}
Expand All @@ -28,8 +30,16 @@ export let source;
*/
export let dev;

export let runes = false;

export let locator = getLocator('', { offsetLine: 1 });

/** @param {string} value */
export function set_source(value) {
source = value;
locator = getLocator(source, { offsetLine: 1 });
}

/**
* @param {AST.SvelteNode & { start?: number | undefined }} node
*/
Expand Down Expand Up @@ -71,8 +81,9 @@ export function pop_ignore() {
*
* @param {(warning: Warning) => boolean} fn
*/
export function reset_warning_filter(fn = () => true) {
export function reset_warnings(fn = () => true) {
warning_filter = fn;
warnings = [];
}

/**
Expand All @@ -85,23 +96,27 @@ export function is_ignored(node, code) {
}

/**
* @param {string} _source
* @param {{ dev?: boolean; filename: string; rootDir?: string }} options
* @param {{
* dev: boolean;
* filename: string;
* component_name?: string;
* rootDir?: string;
* runes: boolean;
* }} state
*/
export function reset(_source, options) {
source = _source;
const root_dir = options.rootDir?.replace(/\\/g, '/');
filename = options.filename.replace(/\\/g, '/');
export function reset(state) {
const root_dir = state.rootDir?.replace(/\\/g, '/');
filename = state.filename.replace(/\\/g, '/');

dev = !!options.dev;
dev = state.dev;
runes = state.runes;
component_name = state.component_name ?? '(unknown)';

if (typeof root_dir === 'string' && filename.startsWith(root_dir)) {
// make filename relative to rootDir
filename = filename.replace(root_dir, '').replace(/^[/\\]/, '');
}

locator = getLocator(source, { offsetLine: 1 });
warnings = [];
ignore_stack = [];
ignore_map.clear();
}