chore: bump esrap (#16240)

* chore: bump esrap

* regenerate
pull/16140/merge
Rich Harris 2 months ago committed by GitHub
parent cf9f8c9c6b
commit e896c55b6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -164,14 +164,14 @@
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@sveltejs/acorn-typescript": "^1.0.5",
"@types/estree": "^1.0.5",
"acorn": "^8.12.1",
"@sveltejs/acorn-typescript": "^1.0.5",
"aria-query": "^5.3.1",
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
"esm-env": "^1.2.1",
"esrap": "^1.4.8",
"esrap": "^2.0.0",
"is-reference": "^3.0.3",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",

@ -1,9 +1,14 @@
/** @import { Node } from 'esrap/languages/ts' */
/** @import * as ESTree from 'estree' */
/** @import { AST } from 'svelte/compiler' */
// @ts-check
import process from 'node:process';
import fs from 'node:fs';
import * as acorn from 'acorn';
import { walk } from 'zimmerframe';
import * as esrap from 'esrap';
import ts from 'esrap/languages/ts';
const DIR = '../../documentation/docs/98-reference/.generated';
@ -97,79 +102,49 @@ function run() {
.readFileSync(new URL(`./templates/${name}.js`, import.meta.url), 'utf-8')
.replace(/\r\n/g, '\n');
/**
* @type {Array<{
* type: string;
* value: string;
* start: number;
* end: number
* }>}
*/
/** @type {AST.JSComment[]} */
const comments = [];
let ast = acorn.parse(source, {
ecmaVersion: 'latest',
sourceType: 'module',
onComment: (block, value, start, end) => {
if (block && /\n/.test(value)) {
let a = start;
while (a > 0 && source[a - 1] !== '\n') a -= 1;
let b = a;
while (/[ \t]/.test(source[b])) b += 1;
const indentation = source.slice(a, b);
value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
}
let ast = /** @type {ESTree.Node} */ (
/** @type {unknown} */ (
acorn.parse(source, {
ecmaVersion: 'latest',
sourceType: 'module',
locations: true,
onComment: comments
})
)
);
comments.push({ type: block ? 'Block' : 'Line', value, start, end });
comments.forEach((comment) => {
if (comment.type === 'Block') {
comment.value = comment.value.replace(/^\t+/gm, '');
}
});
ast = walk(ast, null, {
_(node, { next }) {
let comment;
while (comments[0] && comments[0].start < node.start) {
comment = comments.shift();
// @ts-expect-error
(node.leadingComments ||= []).push(comment);
}
next();
if (comments[0]) {
const slice = source.slice(node.end, comments[0].start);
if (/^[,) \t]*$/.test(slice)) {
// @ts-expect-error
node.trailingComments = [comments.shift()];
}
}
},
// @ts-expect-error
Identifier(node, context) {
if (node.name === 'CODES') {
return {
/** @type {ESTree.ArrayExpression} */
const array = {
type: 'ArrayExpression',
elements: Object.keys(messages[name]).map((code) => ({
type: 'Literal',
value: code
}))
};
return array;
}
}
});
if (comments.length > 0) {
// @ts-expect-error
(ast.trailingComments ||= []).push(...comments);
}
const body = /** @type {ESTree.Program} */ (ast).body;
const category = messages[name];
// find the `export function CODE` node
const index = ast.body.findIndex((node) => {
const index = body.findIndex((node) => {
if (
node.type === 'ExportNamedDeclaration' &&
node.declaration &&
@ -181,8 +156,19 @@ function run() {
if (index === -1) throw new Error(`missing export function CODE in ${name}.js`);
const template_node = ast.body[index];
ast.body.splice(index, 1);
const template_node = body[index];
body.splice(index, 1);
const jsdoc = /** @type {AST.JSComment} */ (
comments.findLast((comment) => comment.start < /** @type {number} */ (template_node.start))
);
const printed = esrap.print(
/** @type {Node} */ (ast),
ts({
comments: comments.filter((comment) => comment !== jsdoc)
})
);
for (const code in category) {
const { messages } = category[code];
@ -203,7 +189,7 @@ function run() {
};
});
/** @type {import('estree').Expression} */
/** @type {ESTree.Expression} */
let message = { type: 'Literal', value: '' };
let prev_vars;
@ -221,10 +207,10 @@ function run() {
const parts = text.split(/(%\w+%)/);
/** @type {import('estree').Expression[]} */
/** @type {ESTree.Expression[]} */
const expressions = [];
/** @type {import('estree').TemplateElement[]} */
/** @type {ESTree.TemplateElement[]} */
const quasis = [];
for (let i = 0; i < parts.length; i += 1) {
@ -244,7 +230,7 @@ function run() {
}
}
/** @type {import('estree').Expression} */
/** @type {ESTree.Expression} */
const expression = {
type: 'TemplateLiteral',
expressions,
@ -272,138 +258,140 @@ function run() {
prev_vars = vars;
}
const clone = walk(/** @type {import('estree').Node} */ (template_node), null, {
// @ts-expect-error Block is a block comment, which is not recognised
Block(node, context) {
if (!node.value.includes('PARAMETER')) return;
const value = /** @type {string} */ (node.value)
.split('\n')
.map((line) => {
if (line === ' * MESSAGE') {
return messages[messages.length - 1]
.split('\n')
.map((line) => ` * ${line}`)
.join('\n');
}
const clone = /** @type {ESTree.Statement} */ (
walk(/** @type {ESTree.Node} */ (template_node), null, {
FunctionDeclaration(node, context) {
if (node.id.name !== 'CODE') return;
if (line.includes('PARAMETER')) {
return vars
.map((name, i) => {
const optional = i >= group[0].vars.length;
const params = [];
return optional
? ` * @param {string | undefined | null} [${name}]`
: ` * @param {string} ${name}`;
})
.join('\n');
for (const param of node.params) {
if (param.type === 'Identifier' && param.name === 'PARAMETER') {
params.push(...vars.map((name) => ({ type: 'Identifier', name })));
} else {
params.push(param);
}
}
return line;
})
.filter((x) => x !== '')
.join('\n');
return /** @type {ESTree.FunctionDeclaration} */ ({
.../** @type {ESTree.FunctionDeclaration} */ (context.next()),
params,
id: {
...node.id,
name: code
}
});
},
TemplateLiteral(node, context) {
/** @type {ESTree.TemplateElement} */
let quasi = {
type: 'TemplateElement',
value: {
...node.quasis[0].value
},
tail: node.quasis[0].tail
};
if (value !== node.value) {
return { ...node, value };
}
},
FunctionDeclaration(node, context) {
if (node.id.name !== 'CODE') return;
/** @type {ESTree.TemplateLiteral} */
let out = {
type: 'TemplateLiteral',
quasis: [quasi],
expressions: []
};
const params = [];
for (let i = 0; i < node.expressions.length; i += 1) {
const q = structuredClone(node.quasis[i + 1]);
const e = node.expressions[i];
for (const param of node.params) {
if (param.type === 'Identifier' && param.name === 'PARAMETER') {
params.push(...vars.map((name) => ({ type: 'Identifier', name })));
} else {
params.push(param);
}
}
if (e.type === 'Literal' && e.value === 'CODE') {
quasi.value.raw += code + q.value.raw;
continue;
}
return /** @type {import('estree').FunctionDeclaration} */ ({
.../** @type {import('estree').FunctionDeclaration} */ (context.next()),
params,
id: {
...node.id,
name: code
}
});
},
TemplateLiteral(node, context) {
/** @type {import('estree').TemplateElement} */
let quasi = {
type: 'TemplateElement',
value: {
...node.quasis[0].value
},
tail: node.quasis[0].tail
};
if (e.type === 'Identifier' && e.name === 'MESSAGE') {
if (message.type === 'Literal') {
const str = /** @type {string} */ (message.value).replace(/(`|\${)/g, '\\$1');
quasi.value.raw += str + q.value.raw;
continue;
}
if (message.type === 'TemplateLiteral') {
const m = structuredClone(message);
quasi.value.raw += m.quasis[0].value.raw;
out.quasis.push(...m.quasis.slice(1));
out.expressions.push(...m.expressions);
quasi = m.quasis[m.quasis.length - 1];
quasi.value.raw += q.value.raw;
continue;
}
}
/** @type {import('estree').TemplateLiteral} */
let out = {
type: 'TemplateLiteral',
quasis: [quasi],
expressions: []
};
out.quasis.push((quasi = q));
out.expressions.push(/** @type {ESTree.Expression} */ (context.visit(e)));
}
for (let i = 0; i < node.expressions.length; i += 1) {
const q = structuredClone(node.quasis[i + 1]);
const e = node.expressions[i];
return out;
},
Literal(node) {
if (node.value === 'CODE') {
return {
type: 'Literal',
value: code
};
}
},
Identifier(node) {
if (node.name !== 'MESSAGE') return;
return message;
}
})
);
if (e.type === 'Literal' && e.value === 'CODE') {
quasi.value.raw += code + q.value.raw;
continue;
const jsdoc_clone = {
...jsdoc,
value: /** @type {string} */ (jsdoc.value)
.split('\n')
.map((line) => {
if (line === ' * MESSAGE') {
return messages[messages.length - 1]
.split('\n')
.map((line) => ` * ${line}`)
.join('\n');
}
if (e.type === 'Identifier' && e.name === 'MESSAGE') {
if (message.type === 'Literal') {
const str = /** @type {string} */ (message.value).replace(/(`|\${)/g, '\\$1');
quasi.value.raw += str + q.value.raw;
continue;
}
if (line.includes('PARAMETER')) {
return vars
.map((name, i) => {
const optional = i >= group[0].vars.length;
if (message.type === 'TemplateLiteral') {
const m = structuredClone(message);
quasi.value.raw += m.quasis[0].value.raw;
out.quasis.push(...m.quasis.slice(1));
out.expressions.push(...m.expressions);
quasi = m.quasis[m.quasis.length - 1];
quasi.value.raw += q.value.raw;
continue;
}
return optional
? ` * @param {string | undefined | null} [${name}]`
: ` * @param {string} ${name}`;
})
.join('\n');
}
out.quasis.push((quasi = q));
out.expressions.push(/** @type {import('estree').Expression} */ (context.visit(e)));
}
return line;
})
.filter((x) => x !== '')
.join('\n')
};
return out;
},
Literal(node) {
if (node.value === 'CODE') {
return {
type: 'Literal',
value: code
};
}
},
Identifier(node) {
if (node.name !== 'MESSAGE') return;
return message;
}
});
const block = esrap.print(
// @ts-expect-error some bullshit
/** @type {ESTree.Program} */ ({ ...ast, body: [clone] }),
ts({ comments: [jsdoc_clone] })
).code;
// @ts-expect-error
ast.body.push(clone);
}
printed.code += `\n\n${block}`;
const module = esrap.print(ast);
body.push(clone);
}
fs.writeFileSync(
dest,
`/* This file is generated by scripts/process-messages/index.js. Do not edit! */\n\n` +
module.code,
printed.code,
'utf-8'
);
}

@ -15,10 +15,12 @@ class InternalCompileError extends Error {
constructor(code, message, position) {
super(message);
this.stack = ''; // avoid unnecessary noise; don't set it as a class property or it becomes enumerable
// We want to extend from Error so that various bundler plugins properly handle it.
// But we also want to share the same object shape with that of warnings, therefore
// we create an instance of the shared class an copy over its properties.
this.#diagnostic = new CompileDiagnostic(code, message, position);
Object.assign(this, this.#diagnostic);
this.name = 'CompileError';
}
@ -816,7 +818,9 @@ export function bind_invalid_expression(node) {
* @returns {never}
*/
export function bind_invalid_name(node, name, explanation) {
e(node, 'bind_invalid_name', `${explanation ? `\`bind:${name}\` is not a valid binding. ${explanation}` : `\`bind:${name}\` is not a valid binding`}\nhttps://svelte.dev/e/bind_invalid_name`);
e(node, 'bind_invalid_name', `${explanation
? `\`bind:${name}\` is not a valid binding. ${explanation}`
: `\`bind:${name}\` is not a valid binding`}\nhttps://svelte.dev/e/bind_invalid_name`);
}
/**

@ -3,7 +3,6 @@
/** @import { AST } from './public.js' */
import { walk as zimmerframe_walk } from 'zimmerframe';
import { convert } from './legacy.js';
import { parse as parse_acorn } from './phases/1-parse/acorn.js';
import { parse as _parse } from './phases/1-parse/index.js';
import { remove_typescript_nodes } from './phases/1-parse/remove_typescript_nodes.js';
import { analyze_component, analyze_module } from './phases/2-analyze/index.js';
@ -69,7 +68,7 @@ export function compileModule(source, options) {
const validated = validate_module_options(options, '');
state.reset(source, validated);
const analysis = analyze_module(parse_acorn(source, false), validated);
const analysis = analyze_module(source, validated);
return transform_module(analysis, source, validated);
}

@ -451,6 +451,7 @@ export function convert(source, ast) {
SpreadAttribute(node) {
return { ...node, type: 'Spread' };
},
// @ts-ignore
StyleSheet(node, context) {
return {
...node,

@ -1,18 +1,32 @@
/** @import { Comment, Program } from 'estree' */
/** @import { AST } from '#compiler' */
import * as acorn from 'acorn';
import { walk } from 'zimmerframe';
import { tsPlugin } from '@sveltejs/acorn-typescript';
const ParserWithTS = acorn.Parser.extend(tsPlugin());
/**
* @typedef {Comment & {
* start: number;
* end: number;
* }} CommentWithLocation
*/
/**
* @param {string} source
* @param {AST.JSComment[]} comments
* @param {boolean} typescript
* @param {boolean} [is_script]
*/
export function parse(source, typescript, is_script) {
export function parse(source, comments, typescript, is_script) {
const parser = typescript ? ParserWithTS : acorn.Parser;
const { onComment, add_comments } = get_comment_handlers(source);
const { onComment, add_comments } = get_comment_handlers(
source,
/** @type {CommentWithLocation[]} */ (comments)
);
// @ts-ignore
const parse_statement = parser.prototype.parseStatement;
@ -53,13 +67,19 @@ export function parse(source, typescript, is_script) {
/**
* @param {string} source
* @param {Comment[]} comments
* @param {boolean} typescript
* @param {number} index
* @returns {acorn.Expression & { leadingComments?: CommentWithLocation[]; trailingComments?: CommentWithLocation[]; }}
*/
export function parse_expression_at(source, typescript, index) {
export function parse_expression_at(source, comments, typescript, index) {
const parser = typescript ? ParserWithTS : acorn.Parser;
const { onComment, add_comments } = get_comment_handlers(source);
const { onComment, add_comments } = get_comment_handlers(
source,
/** @type {CommentWithLocation[]} */ (comments),
index
);
const ast = parser.parseExpressionAt(source, index, {
onComment,
@ -78,26 +98,20 @@ export function parse_expression_at(source, typescript, index) {
* to add them after the fact. They are needed in order to support `svelte-ignore` comments
* in JS code and so that `prettier-plugin-svelte` doesn't remove all comments when formatting.
* @param {string} source
* @param {CommentWithLocation[]} comments
* @param {number} index
*/
function get_comment_handlers(source) {
/**
* @typedef {Comment & {
* start: number;
* end: number;
* }} CommentWithLocation
*/
/** @type {CommentWithLocation[]} */
const comments = [];
function get_comment_handlers(source, comments, index = 0) {
return {
/**
* @param {boolean} block
* @param {string} value
* @param {number} start
* @param {number} end
* @param {import('acorn').Position} [start_loc]
* @param {import('acorn').Position} [end_loc]
*/
onComment: (block, value, start, end) => {
onComment: (block, value, start, end, start_loc, end_loc) => {
if (block && /\n/.test(value)) {
let a = start;
while (a > 0 && source[a - 1] !== '\n') a -= 1;
@ -109,13 +123,26 @@ function get_comment_handlers(source) {
value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
}
comments.push({ type: block ? 'Block' : 'Line', value, start, end });
comments.push({
type: block ? 'Block' : 'Line',
value,
start,
end,
loc: {
start: /** @type {import('acorn').Position} */ (start_loc),
end: /** @type {import('acorn').Position} */ (end_loc)
}
});
},
/** @param {acorn.Node & { leadingComments?: CommentWithLocation[]; trailingComments?: CommentWithLocation[]; }} ast */
add_comments(ast) {
if (comments.length === 0) return;
comments = comments
.filter((comment) => comment.start >= index)
.map(({ type, value, start, end }) => ({ type, value, start, end }));
walk(ast, null, {
_(node, { next, path }) {
let comment;

@ -1,4 +1,5 @@
/** @import { AST } from '#compiler' */
/** @import { Comment } from 'estree' */
// @ts-expect-error acorn type definitions are borked in the release we use
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import fragment from './state/fragment.js';
@ -87,6 +88,7 @@ export class Parser {
type: 'Root',
fragment: create_fragment(),
options: null,
comments: [],
metadata: {
ts: this.ts
}

@ -59,7 +59,12 @@ export default function read_pattern(parser) {
space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1);
const expression = /** @type {any} */ (
parse_expression_at(`${space_with_newline}(${pattern_string} = 1)`, parser.ts, start - 1)
parse_expression_at(
`${space_with_newline}(${pattern_string} = 1)`,
parser.root.comments,
parser.ts,
start - 1
)
).left;
expression.typeAnnotation = read_type_annotation(parser);
@ -96,13 +101,13 @@ function read_type_annotation(parser) {
// parameters as part of a sequence expression instead, and will then error on optional
// parameters (`?:`). Therefore replace that sequence with something that will not error.
parser.template.slice(parser.index).replace(/\?\s*:/g, ':');
let expression = parse_expression_at(template, parser.ts, a);
let expression = parse_expression_at(template, parser.root.comments, parser.ts, a);
// `foo: bar = baz` gets mangled — fix it
if (expression.type === 'AssignmentExpression') {
let b = expression.right.start;
while (template[b] !== '=') b -= 1;
expression = parse_expression_at(template.slice(0, b), parser.ts, a);
expression = parse_expression_at(template.slice(0, b), parser.root.comments, parser.ts, a);
}
// `array as item: string, index` becomes `string, index`, which is mistaken as a sequence expression - fix that

@ -34,12 +34,24 @@ export function get_loose_identifier(parser, opening_token) {
*/
export default function read_expression(parser, opening_token, disallow_loose) {
try {
const node = parse_expression_at(parser.template, parser.ts, parser.index);
let comment_index = parser.root.comments.length;
const node = parse_expression_at(
parser.template,
parser.root.comments,
parser.ts,
parser.index
);
let num_parens = 0;
if (node.leadingComments !== undefined && node.leadingComments.length > 0) {
parser.index = node.leadingComments.at(-1).end;
let i = parser.root.comments.length;
while (i-- > comment_index) {
const comment = parser.root.comments[i];
if (comment.end < node.start) {
parser.index = comment.end;
break;
}
}
for (let i = parser.index; i < /** @type {number} */ (node.start); i += 1) {
@ -47,9 +59,9 @@ export default function read_expression(parser, opening_token, disallow_loose) {
}
let index = /** @type {number} */ (node.end);
if (node.trailingComments !== undefined && node.trailingComments.length > 0) {
index = node.trailingComments.at(-1).end;
}
const last_comment = parser.root.comments.at(-1);
if (last_comment && last_comment.end > index) index = last_comment.end;
while (num_parens > 0) {
const char = parser.template[index];

@ -34,7 +34,7 @@ export function read_script(parser, start, attributes) {
let ast;
try {
ast = acorn.parse(source, parser.ts, true);
ast = acorn.parse(source, parser.root.comments, parser.ts, true);
} catch (err) {
parser.acorn_error(err);
}

@ -398,7 +398,12 @@ function open(parser) {
let function_expression = matched
? /** @type {ArrowFunctionExpression} */ (
parse_expression_at(prelude + `${params} => {}`, parser.ts, params_start)
parse_expression_at(
prelude + `${params} => {}`,
parser.root.comments,
parser.ts,
params_start
)
)
: { params: [] };

@ -1,8 +1,9 @@
/** @import { Expression, Node, Program } from 'estree' */
/** @import { Comment, Expression, Node, Program } from 'estree' */
/** @import { Binding, AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { AnalysisState, Visitors } from './types' */
/** @import { Analysis, ComponentAnalysis, Js, ReactiveStatement, Template } from '../types' */
import { walk } from 'zimmerframe';
import { parse } from '../1-parse/acorn.js';
import * as e from '../../errors.js';
import * as w from '../../warnings.js';
import { extract_identifiers } from '../../utils/ast.js';
@ -231,11 +232,16 @@ function get_component_name(filename) {
const RESERVED = ['$$props', '$$restProps', '$$slots'];
/**
* @param {Program} ast
* @param {string} source
* @param {ValidatedModuleCompileOptions} options
* @returns {Analysis}
*/
export function analyze_module(ast, options) {
export function analyze_module(source, options) {
/** @type {AST.JSComment[]} */
const comments = [];
const ast = parse(source, comments, false, false);
const { scope, scopes } = create_scopes(ast, new ScopeRoot(), false, null);
for (const [name, references] of scope.references) {
@ -259,6 +265,7 @@ export function analyze_module(ast, options) {
runes: true,
immutable: true,
tracing: false,
comments,
classes: new Map()
};
@ -429,6 +436,7 @@ export function analyze_component(root, source, options) {
module,
instance,
template,
comments: root.comments,
elements: [],
runes,
// if we are not in runes mode but we have no reserved references ($$props, $$restProps)

@ -362,6 +362,9 @@ export function client_component(analysis, options) {
.../** @type {ESTree.Statement[]} */ (template.body)
]);
// trick esrap into including comments
component_block.loc = instance.loc;
if (!analysis.runes) {
// Bind static exports to props so that people can access them with bind:x
for (const { name, alias } of analysis.exports) {

@ -1,6 +1,8 @@
/** @import { Node } from 'esrap/languages/ts' */
/** @import { ValidatedCompileOptions, CompileResult, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis, Analysis } from '../types' */
import { print } from 'esrap';
import ts from 'esrap/languages/ts';
import { VERSION } from '../../../version.js';
import { server_component, server_module } from './server/transform-server.js';
import { client_component, client_module } from './client/transform-client.js';
@ -34,7 +36,7 @@ export function transform_component(analysis, source, options) {
const js_source_name = get_source_name(options.filename, options.outputFilename, 'input.svelte');
const js = print(program, {
const js = print(/** @type {Node} */ (program), ts({ comments: analysis.comments }), {
// include source content; makes it easier/more robust looking up the source map code
// (else esrap does return null for source and sourceMapContent which may trip up tooling)
sourceMapContent: source,
@ -93,13 +95,19 @@ export function transform_module(analysis, source, options) {
];
}
const js = print(/** @type {Node} */ (program), ts({ comments: analysis.comments }), {
// include source content; makes it easier/more robust looking up the source map code
// (else esrap does return null for source and sourceMapContent which may trip up tooling)
sourceMapContent: source,
sourceMapSource: get_source_name(options.filename, undefined, 'input.svelte.js')
});
// prepend comment
js.code = `/* ${basename} generated by Svelte v${VERSION} */\n${js.code}`;
js.map.mappings = ';' + js.map.mappings;
return {
js: print(program, {
// include source content; makes it easier/more robust looking up the source map code
// (else esrap does return null for source and sourceMapContent which may trip up tooling)
sourceMapContent: source,
sourceMapSource: get_source_name(options.filename, undefined, 'input.svelte.js')
}),
js,
css: null,
metadata: {
runes: true

@ -242,6 +242,9 @@ export function server_component(analysis, options) {
.../** @type {Statement[]} */ (template.body)
]);
// trick esrap into including comments
component_block.loc = instance.loc;
if (analysis.props_id) {
// need to be placed on first line of the component for hydration
component_block.body.unshift(

@ -2,6 +2,7 @@ import type { AST, Binding, StateField } from '#compiler';
import type {
AssignmentExpression,
ClassBody,
Comment,
Identifier,
LabeledStatement,
Node,
@ -37,6 +38,7 @@ export interface Analysis {
runes: boolean;
immutable: boolean;
tracing: boolean;
comments: AST.JSComment[];
classes: Map<ClassBody, Map<string, StateField>>;

@ -72,6 +72,8 @@ export namespace AST {
instance: Script | null;
/** The parsed `<script module>` element, if exists */
module: Script | null;
/** Comments found in <script> and {expressions} */
comments: JSComment[];
/** @internal */
metadata: {
/** Whether the component was parsed with typescript */
@ -537,6 +539,17 @@ export namespace AST {
attributes: Attribute[];
}
export interface JSComment {
type: 'Line' | 'Block';
value: string;
start: number;
end: number;
loc: {
start: { line: number; column: number };
end: { line: number; column: number };
};
}
export type AttributeLike = Attribute | SpreadAttribute | Directive;
export type Directive =
@ -593,7 +606,7 @@ export namespace AST {
| AST.Comment
| Block;
export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node;
export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node | Script;
export type { _CSS as CSS };
}

@ -398,10 +398,13 @@ export function merge_with_preprocessor_map(result, options, source_name) {
// map may contain a different file name. Patch our map beforehand to align sources so merging
// with the preprocessor map works correctly.
result.map.sources = [file_basename];
result.map = apply_preprocessor_sourcemap(
file_basename,
Object.assign(
result.map,
/** @type {any} */ (options.sourcemap)
apply_preprocessor_sourcemap(
file_basename,
result.map,
/** @type {any} */ (options.sourcemap)
)
);
// After applying the preprocessor map, we need to do the inverse and make the sources
// relative to the input file again in case the output code is in a different directory.

@ -1,12 +1,6 @@
/* This file is generated by scripts/process-messages/index.js. Do not edit! */
import {
warnings,
ignore_stack,
ignore_map,
warning_filter
} from './state.js';
import { warnings, ignore_stack, ignore_map, warning_filter } from './state.js';
import { CompileDiagnostic } from './utils/compile_diagnostic.js';
/** @typedef {{ start?: number, end?: number }} NodeLike */
@ -40,6 +34,7 @@ function w(node, code, message) {
const warning = new InternalCompileWarning(code, message, node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined);
if (!warning_filter(warning)) return;
warnings.push(warning);
}
@ -496,7 +491,9 @@ export function a11y_role_supports_aria_props_implicit(node, attribute, role, na
* @param {string | undefined | null} [suggestion]
*/
export function a11y_unknown_aria_attribute(node, attribute, suggestion) {
w(node, 'a11y_unknown_aria_attribute', `${suggestion ? `Unknown aria attribute 'aria-${attribute}'. Did you mean '${suggestion}'?` : `Unknown aria attribute 'aria-${attribute}'`}\nhttps://svelte.dev/e/a11y_unknown_aria_attribute`);
w(node, 'a11y_unknown_aria_attribute', `${suggestion
? `Unknown aria attribute 'aria-${attribute}'. Did you mean '${suggestion}'?`
: `Unknown aria attribute 'aria-${attribute}'`}\nhttps://svelte.dev/e/a11y_unknown_aria_attribute`);
}
/**
@ -506,7 +503,9 @@ export function a11y_unknown_aria_attribute(node, attribute, suggestion) {
* @param {string | undefined | null} [suggestion]
*/
export function a11y_unknown_role(node, role, suggestion) {
w(node, 'a11y_unknown_role', `${suggestion ? `Unknown role '${role}'. Did you mean '${suggestion}'?` : `Unknown role '${role}'`}\nhttps://svelte.dev/e/a11y_unknown_role`);
w(node, 'a11y_unknown_role', `${suggestion
? `Unknown role '${role}'. Did you mean '${suggestion}'?`
: `Unknown role '${role}'`}\nhttps://svelte.dev/e/a11y_unknown_role`);
}
/**
@ -534,7 +533,9 @@ export function legacy_code(node, code, suggestion) {
* @param {string | undefined | null} [suggestion]
*/
export function unknown_code(node, code, suggestion) {
w(node, 'unknown_code', `${suggestion ? `\`${code}\` is not a recognised code (did you mean \`${suggestion}\`?)` : `\`${code}\` is not a recognised code`}\nhttps://svelte.dev/e/unknown_code`);
w(node, 'unknown_code', `${suggestion
? `\`${code}\` is not a recognised code (did you mean \`${suggestion}\`?)`
: `\`${code}\` is not a recognised code`}\nhttps://svelte.dev/e/unknown_code`);
}
/**

@ -11,6 +11,7 @@ export function bind_invalid_checkbox_value() {
const error = new Error(`bind_invalid_checkbox_value\nUsing \`bind:value\` together with a checkbox input is not allowed. Use \`bind:checked\` instead\nhttps://svelte.dev/e/bind_invalid_checkbox_value`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/bind_invalid_checkbox_value`);
@ -29,6 +30,7 @@ export function bind_invalid_export(component, key, name) {
const error = new Error(`bind_invalid_export\nComponent ${component} has an export named \`${key}\` that a consumer component is trying to access using \`bind:${key}\`, which is disallowed. Instead, use \`bind:this\` (e.g. \`<${name} bind:this={component} />\`) and then access the property on the bound component instance (e.g. \`component.${key}\`)\nhttps://svelte.dev/e/bind_invalid_export`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/bind_invalid_export`);
@ -47,6 +49,7 @@ export function bind_not_bindable(key, component, name) {
const error = new Error(`bind_not_bindable\nA component is attempting to bind to a non-bindable property \`${key}\` belonging to ${component} (i.e. \`<${name} bind:${key}={...}>\`). To mark a property as bindable: \`let { ${key} = $bindable() } = $props()\`\nhttps://svelte.dev/e/bind_not_bindable`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/bind_not_bindable`);
@ -64,6 +67,7 @@ export function component_api_changed(method, component) {
const error = new Error(`component_api_changed\nCalling \`${method}\` on a component instance (of ${component}) is no longer valid in Svelte 5\nhttps://svelte.dev/e/component_api_changed`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/component_api_changed`);
@ -81,6 +85,7 @@ export function component_api_invalid_new(component, name) {
const error = new Error(`component_api_invalid_new\nAttempted to instantiate ${component} with \`new ${name}\`, which is no longer valid in Svelte 5. If this component is not under your control, set the \`compatibility.componentApi\` compiler option to \`4\` to keep it working.\nhttps://svelte.dev/e/component_api_invalid_new`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/component_api_invalid_new`);
@ -96,6 +101,7 @@ export function derived_references_self() {
const error = new Error(`derived_references_self\nA derived value cannot reference itself recursively\nhttps://svelte.dev/e/derived_references_self`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/derived_references_self`);
@ -111,9 +117,12 @@ export function derived_references_self() {
*/
export function each_key_duplicate(a, b, value) {
if (DEV) {
const error = new Error(`each_key_duplicate\n${value ? `Keyed each block has duplicate key \`${value}\` at indexes ${a} and ${b}` : `Keyed each block has duplicate key at indexes ${a} and ${b}`}\nhttps://svelte.dev/e/each_key_duplicate`);
const error = new Error(`each_key_duplicate\n${value
? `Keyed each block has duplicate key \`${value}\` at indexes ${a} and ${b}`
: `Keyed each block has duplicate key at indexes ${a} and ${b}`}\nhttps://svelte.dev/e/each_key_duplicate`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/each_key_duplicate`);
@ -130,6 +139,7 @@ export function effect_in_teardown(rune) {
const error = new Error(`effect_in_teardown\n\`${rune}\` cannot be used inside an effect cleanup function\nhttps://svelte.dev/e/effect_in_teardown`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/effect_in_teardown`);
@ -145,6 +155,7 @@ export function effect_in_unowned_derived() {
const error = new Error(`effect_in_unowned_derived\nEffect cannot be created inside a \`$derived\` value that was not itself created inside an effect\nhttps://svelte.dev/e/effect_in_unowned_derived`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/effect_in_unowned_derived`);
@ -161,6 +172,7 @@ export function effect_orphan(rune) {
const error = new Error(`effect_orphan\n\`${rune}\` can only be used inside an effect (e.g. during component initialisation)\nhttps://svelte.dev/e/effect_orphan`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/effect_orphan`);
@ -176,6 +188,7 @@ export function effect_update_depth_exceeded() {
const error = new Error(`effect_update_depth_exceeded\nMaximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops\nhttps://svelte.dev/e/effect_update_depth_exceeded`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/effect_update_depth_exceeded`);
@ -191,6 +204,7 @@ export function hydration_failed() {
const error = new Error(`hydration_failed\nFailed to hydrate the application\nhttps://svelte.dev/e/hydration_failed`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/hydration_failed`);
@ -206,6 +220,7 @@ export function invalid_snippet() {
const error = new Error(`invalid_snippet\nCould not \`{@render}\` snippet due to the expression being \`null\` or \`undefined\`. Consider using optional chaining \`{@render snippet?.()}\`\nhttps://svelte.dev/e/invalid_snippet`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/invalid_snippet`);
@ -222,6 +237,7 @@ export function lifecycle_legacy_only(name) {
const error = new Error(`lifecycle_legacy_only\n\`${name}(...)\` cannot be used in runes mode\nhttps://svelte.dev/e/lifecycle_legacy_only`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/lifecycle_legacy_only`);
@ -238,6 +254,7 @@ export function props_invalid_value(key) {
const error = new Error(`props_invalid_value\nCannot do \`bind:${key}={undefined}\` when \`${key}\` has a fallback value\nhttps://svelte.dev/e/props_invalid_value`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/props_invalid_value`);
@ -254,6 +271,7 @@ export function props_rest_readonly(property) {
const error = new Error(`props_rest_readonly\nRest element properties of \`$props()\` such as \`${property}\` are readonly\nhttps://svelte.dev/e/props_rest_readonly`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/props_rest_readonly`);
@ -270,6 +288,7 @@ export function rune_outside_svelte(rune) {
const error = new Error(`rune_outside_svelte\nThe \`${rune}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files\nhttps://svelte.dev/e/rune_outside_svelte`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/rune_outside_svelte`);
@ -285,6 +304,7 @@ export function state_descriptors_fixed() {
const error = new Error(`state_descriptors_fixed\nProperty descriptors defined on \`$state\` objects must contain \`value\` and always be \`enumerable\`, \`configurable\` and \`writable\`.\nhttps://svelte.dev/e/state_descriptors_fixed`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/state_descriptors_fixed`);
@ -300,6 +320,7 @@ export function state_prototype_fixed() {
const error = new Error(`state_prototype_fixed\nCannot set prototype of \`$state\` object\nhttps://svelte.dev/e/state_prototype_fixed`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/state_prototype_fixed`);
@ -315,6 +336,7 @@ export function state_unsafe_mutation() {
const error = new Error(`state_unsafe_mutation\nUpdating state inside \`$derived(...)\`, \`$inspect(...)\` or a template expression is forbidden. If the value should not be reactive, declare it without \`$state\`\nhttps://svelte.dev/e/state_unsafe_mutation`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/state_unsafe_mutation`);

@ -25,7 +25,13 @@ export function assignment_value_stale(property, location) {
*/
export function binding_property_non_reactive(binding, location) {
if (DEV) {
console.warn(`%c[svelte] binding_property_non_reactive\n%c${location ? `\`${binding}\` (${location}) is binding to a non-reactive property` : `\`${binding}\` is binding to a non-reactive property`}\nhttps://svelte.dev/e/binding_property_non_reactive`, bold, normal);
console.warn(
`%c[svelte] binding_property_non_reactive\n%c${location
? `\`${binding}\` (${location}) is binding to a non-reactive property`
: `\`${binding}\` is binding to a non-reactive property`}\nhttps://svelte.dev/e/binding_property_non_reactive`,
bold,
normal
);
} else {
console.warn(`https://svelte.dev/e/binding_property_non_reactive`);
}
@ -76,7 +82,13 @@ export function hydration_attribute_changed(attribute, html, value) {
*/
export function hydration_html_changed(location) {
if (DEV) {
console.warn(`%c[svelte] hydration_html_changed\n%c${location ? `The value of an \`{@html ...}\` block ${location} changed between server and client renders. The client value will be ignored in favour of the server value` : 'The value of an `{@html ...}` block changed between server and client renders. The client value will be ignored in favour of the server value'}\nhttps://svelte.dev/e/hydration_html_changed`, bold, normal);
console.warn(
`%c[svelte] hydration_html_changed\n%c${location
? `The value of an \`{@html ...}\` block ${location} changed between server and client renders. The client value will be ignored in favour of the server value`
: 'The value of an `{@html ...}` block changed between server and client renders. The client value will be ignored in favour of the server value'}\nhttps://svelte.dev/e/hydration_html_changed`,
bold,
normal
);
} else {
console.warn(`https://svelte.dev/e/hydration_html_changed`);
}
@ -88,7 +100,13 @@ export function hydration_html_changed(location) {
*/
export function hydration_mismatch(location) {
if (DEV) {
console.warn(`%c[svelte] hydration_mismatch\n%c${location ? `Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near ${location}` : 'Hydration failed because the initial UI does not match what was rendered on the server'}\nhttps://svelte.dev/e/hydration_mismatch`, bold, normal);
console.warn(
`%c[svelte] hydration_mismatch\n%c${location
? `Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near ${location}`
: 'Hydration failed because the initial UI does not match what was rendered on the server'}\nhttps://svelte.dev/e/hydration_mismatch`,
bold,
normal
);
} else {
console.warn(`https://svelte.dev/e/hydration_mismatch`);
}

@ -1,5 +1,7 @@
/* This file is generated by scripts/process-messages/index.js. Do not edit! */
/**
* `%name%(...)` is not available on the server
* @param {string} name
@ -9,5 +11,6 @@ export function lifecycle_function_unavailable(name) {
const error = new Error(`lifecycle_function_unavailable\n\`${name}(...)\` is not available on the server\nhttps://svelte.dev/e/lifecycle_function_unavailable`);
error.name = 'Svelte error';
throw error;
}

@ -11,6 +11,7 @@ export function invalid_default_snippet() {
const error = new Error(`invalid_default_snippet\nCannot use \`{@render children(...)}\` if the parent component uses \`let:\` directives. Consider using a named snippet instead\nhttps://svelte.dev/e/invalid_default_snippet`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/invalid_default_snippet`);
@ -26,6 +27,7 @@ export function invalid_snippet_arguments() {
const error = new Error(`invalid_snippet_arguments\nA snippet function was passed invalid arguments. Snippets should only be instantiated via \`{@render ...}\`\nhttps://svelte.dev/e/invalid_snippet_arguments`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/invalid_snippet_arguments`);
@ -42,6 +44,7 @@ export function lifecycle_outside_component(name) {
const error = new Error(`lifecycle_outside_component\n\`${name}(...)\` can only be used during component initialisation\nhttps://svelte.dev/e/lifecycle_outside_component`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/lifecycle_outside_component`);
@ -57,6 +60,7 @@ export function snippet_without_render_tag() {
const error = new Error(`snippet_without_render_tag\nAttempted to render a snippet without a \`{@render}\` block. This would cause the snippet code to be stringified instead of its content being rendered to the DOM. To fix this, change \`{snippet}\` to \`{@render snippet()}\`.\nhttps://svelte.dev/e/snippet_without_render_tag`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/snippet_without_render_tag`);
@ -73,6 +77,7 @@ export function store_invalid_shape(name) {
const error = new Error(`store_invalid_shape\n\`${name}\` is not a store with a \`subscribe\` method\nhttps://svelte.dev/e/store_invalid_shape`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/store_invalid_shape`);
@ -88,6 +93,7 @@ export function svelte_element_invalid_this_value() {
const error = new Error(`svelte_element_invalid_this_value\nThe \`this\` prop on \`<svelte:element>\` must be a string, if defined\nhttps://svelte.dev/e/svelte_element_invalid_this_value`);
error.name = 'Svelte error';
throw error;
} else {
throw new Error(`https://svelte.dev/e/svelte_element_invalid_this_value`);

@ -25,11 +25,15 @@ export function dynamic_void_element_content(tag) {
*/
export function state_snapshot_uncloneable(properties) {
if (DEV) {
console.warn(`%c[svelte] state_snapshot_uncloneable\n%c${properties
? `The following properties cannot be cloned with \`$state.snapshot\` — the return value contains the originals:
console.warn(
`%c[svelte] state_snapshot_uncloneable\n%c${properties
? `The following properties cannot be cloned with \`$state.snapshot\` — the return value contains the originals:
${properties}`
: 'Value cannot be cloned with `$state.snapshot` — the original value was returned'}\nhttps://svelte.dev/e/state_snapshot_uncloneable`, bold, normal);
: 'Value cannot be cloned with `$state.snapshot` — the original value was returned'}\nhttps://svelte.dev/e/state_snapshot_uncloneable`,
bold,
normal
);
} else {
console.warn(`https://svelte.dev/e/state_snapshot_uncloneable`);
}

@ -21,6 +21,8 @@ const { test, run } = suite<ParserTest>(async (config, cwd) => {
)
);
delete actual.comments;
// run `UPDATE_SNAPSHOTS=true pnpm test parser` to update parser tests
if (process.env.UPDATE_SNAPSHOTS) {
fs.writeFileSync(`${cwd}/output.json`, JSON.stringify(actual, null, '\t'));

@ -22,6 +22,7 @@ export default function Bind_component_snippet($$anchor) {
get value() {
return $.get(value);
},
set value($$value) {
$.set(value, $$value, true);
}

@ -16,6 +16,7 @@ export default function Bind_component_snippet($$payload) {
get value() {
return value;
},
set value($$value) {
value = $$value;
$$settled = false;

@ -6,6 +6,7 @@ var root = $.from_html(`<div></div> <svg></svg> <custom-element></custom-element
export default function Main($$anchor) {
// needs to be a snapshot test because jsdom does auto-correct the attribute casing
let x = 'test';
let y = () => 'test';
var fragment = root();
var div = $.first_child(fragment);

@ -3,6 +3,7 @@ import * as $ from 'svelte/internal/server';
export default function Main($$payload) {
// needs to be a snapshot test because jsdom does auto-correct the attribute casing
let x = 'test';
let y = () => 'test';
$$payload.out += `<div${$.attr('foobar', x)}></div> <svg${$.attr('viewBox', x)}></svg> <custom-element${$.attr('foobar', x)}></custom-element> <div${$.attr('foobar', y())}></div> <svg${$.attr('viewBox', y())}></svg> <custom-element${$.attr('foobar', y())}></custom-element>`;

@ -14,6 +14,7 @@ export default function Function_prop_no_getter($$anchor) {
onmousedown: () => $.set(count, $.get(count) + 1),
onmouseup,
onmouseenter: () => $.set(count, plusOne($.get(count)), true),
children: ($$anchor, $$slotProps) => {
$.next();
@ -22,6 +23,7 @@ export default function Function_prop_no_getter($$anchor) {
$.template_effect(() => $.set_text(text, `clicks: ${$.get(count) ?? ''}`));
$.append($$anchor, text);
},
$$slots: { default: true }
});
}

@ -13,9 +13,11 @@ export default function Function_prop_no_getter($$payload) {
onmousedown: () => count += 1,
onmouseup,
onmouseenter: () => count = plusOne(count),
children: ($$payload) => {
$$payload.out += `<!---->clicks: ${$.escape(count)}`;
},
$$slots: { default: true }
});
}

@ -6,6 +6,7 @@ var root = $.from_tree(
[
['h1', null, 'hello'],
' ',
[
'div',
{ class: 'potato' },

@ -3,6 +3,4 @@ import 'svelte/internal/flags/legacy';
import * as $ from 'svelte/internal/client';
import { random } from './module.svelte';
export default function Imports_in_modules($$anchor) {
}
export default function Imports_in_modules($$anchor) {}

@ -1,6 +1,4 @@
import * as $ from 'svelte/internal/server';
import { random } from './module.svelte';
export default function Imports_in_modules($$payload) {
}
export default function Imports_in_modules($$payload) {}

@ -1120,6 +1120,8 @@ declare module 'svelte/compiler' {
instance: Script | null;
/** The parsed `<script module>` element, if exists */
module: Script | null;
/** Comments found in <script> and {expressions} */
comments: JSComment[];
}
export interface SvelteOptions {
@ -1437,6 +1439,17 @@ declare module 'svelte/compiler' {
attributes: Attribute[];
}
export interface JSComment {
type: 'Line' | 'Block';
value: string;
start: number;
end: number;
loc: {
start: { line: number; column: number };
end: { line: number; column: number };
};
}
export type AttributeLike = Attribute | SpreadAttribute | Directive;
export type Directive =
@ -1493,7 +1506,7 @@ declare module 'svelte/compiler' {
| AST.Comment
| Block;
export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node;
export type SvelteNode = Node | TemplateNode | AST.Fragment | _CSS.Node | Script;
export type { _CSS as CSS };
}

@ -87,8 +87,8 @@ importers:
specifier: ^1.2.1
version: 1.2.1
esrap:
specifier: ^1.4.8
version: 1.4.8
specifier: ^2.0.0
version: 2.0.0
is-reference:
specifier: ^3.0.3
version: 3.0.3
@ -1261,8 +1261,8 @@ packages:
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
engines: {node: '>=0.10'}
esrap@1.4.8:
resolution: {integrity: sha512-jlENbjZ7lqgJV9/OmgAtVqrFFMwsl70ctOgPIg5oTdQVGC13RSkMdtvAmu7ZTLax92c9ljnIG0xleEkdL69hwg==}
esrap@2.0.0:
resolution: {integrity: sha512-zhw1TDqno99Ld5wOpe0t47rzVyxfGc1fvxNzPsqk4idUf5dcAePkAyfTceLJaSTytjiWDu26S5tI+grjvymXJA==}
esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
@ -3622,7 +3622,7 @@ snapshots:
dependencies:
estraverse: 5.3.0
esrap@1.4.8:
esrap@2.0.0:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0

Loading…
Cancel
Save