@ -1,5 +1,5 @@
/** @import { Expression } from 'estree' */
/** @import { Expression } from 'estree' */
/** @import * as Compiler from '#compiler' */
/** @import { AST, Directive, ElementLike, TemplateNode } from '#compiler' */
/** @import { Parser } from '../index.js' */
/** @import { Parser } from '../index.js' */
import { is _void } from '../../../../utils.js' ;
import { is _void } from '../../../../utils.js' ;
import read _expression from '../read/expression.js' ;
import read _expression from '../read/expression.js' ;
@ -26,7 +26,7 @@ const regex_valid_element_name =
const regex _valid _component _name =
const regex _valid _component _name =
/^(?:[A-Z][A-Za-z0-9_$.]*|[a-z][A-Za-z0-9_$]*(?:\.[A-Za-z0-9_$]+)+)$/ ;
/^(?:[A-Z][A-Za-z0-9_$.]*|[a-z][A-Za-z0-9_$]*(?:\.[A-Za-z0-9_$]+)+)$/ ;
/** @type {Map<string, Compiler. ElementLike['type']>} */
/** @type {Map<string, ElementLike['type']>} */
const root _only _meta _tags = new Map ( [
const root _only _meta _tags = new Map ( [
[ 'svelte:head' , 'SvelteHead' ] ,
[ 'svelte:head' , 'SvelteHead' ] ,
[ 'svelte:options' , 'SvelteOptions' ] ,
[ 'svelte:options' , 'SvelteOptions' ] ,
@ -35,7 +35,7 @@ const root_only_meta_tags = new Map([
[ 'svelte:body' , 'SvelteBody' ]
[ 'svelte:body' , 'SvelteBody' ]
] ) ;
] ) ;
/** @type {Map<string, Compiler. ElementLike['type']>} */
/** @type {Map<string, ElementLike['type']>} */
const meta _tags = new Map ( [
const meta _tags = new Map ( [
... root _only _meta _tags ,
... root _only _meta _tags ,
[ 'svelte:element' , 'SvelteElement' ] ,
[ 'svelte:element' , 'SvelteElement' ] ,
@ -54,7 +54,7 @@ export default function element(parser) {
const data = parser . read _until ( regex _closing _comment ) ;
const data = parser . read _until ( regex _closing _comment ) ;
parser . eat ( '-->' , true ) ;
parser . eat ( '-->' , true ) ;
/** @type {ReturnType<typeof parser.append< Compiler .Comment>>} */
/** @type {ReturnType<typeof parser.append< AST .Comment>>} */
parser . append ( {
parser . append ( {
type : 'Comment' ,
type : 'Comment' ,
start ,
start ,
@ -77,7 +77,7 @@ export default function element(parser) {
}
}
// close any elements that don't have their own closing tags, e.g. <div><p></div>
// close any elements that don't have their own closing tags, e.g. <div><p></div>
while ( /** @type { Compiler .RegularElement} */ ( parent ) . name !== name ) {
while ( /** @type { AST .RegularElement} */ ( parent ) . name !== name ) {
if ( parent . type !== 'RegularElement' ) {
if ( parent . type !== 'RegularElement' ) {
if ( parser . last _auto _closed _tag && parser . last _auto _closed _tag . tag === name ) {
if ( parser . last _auto _closed _tag && parser . last _auto _closed _tag . tag === name ) {
e . element _invalid _closing _tag _autoclosed ( start , name , parser . last _auto _closed _tag . reason ) ;
e . element _invalid _closing _tag _autoclosed ( start , name , parser . last _auto _closed _tag . reason ) ;
@ -135,7 +135,7 @@ export default function element(parser) {
? 'SlotElement'
? 'SlotElement'
: 'RegularElement' ;
: 'RegularElement' ;
/** @type { Compiler. ElementLike} */
/** @type { ElementLike} */
const element =
const element =
type === 'RegularElement'
type === 'RegularElement'
? {
? {
@ -153,7 +153,7 @@ export default function element(parser) {
} ,
} ,
parent : null
parent : null
}
}
: /** @type { Compiler. ElementLike} */ ( {
: /** @type { ElementLike} */ ( {
type ,
type ,
start ,
start ,
end : - 1 ,
end : - 1 ,
@ -211,7 +211,7 @@ export default function element(parser) {
e . svelte _component _missing _this ( start ) ;
e . svelte _component _missing _this ( start ) ;
}
}
const definition = /** @type { Compiler .Attribute} */ ( element . attributes . splice ( index , 1 ) [ 0 ] ) ;
const definition = /** @type { AST .Attribute} */ ( element . attributes . splice ( index , 1 ) [ 0 ] ) ;
if ( ! is _expression _attribute ( definition ) ) {
if ( ! is _expression _attribute ( definition ) ) {
e . svelte _component _invalid _this ( definition . start ) ;
e . svelte _component _invalid _this ( definition . start ) ;
}
}
@ -228,7 +228,7 @@ export default function element(parser) {
e . svelte _element _missing _this ( start ) ;
e . svelte _element _missing _this ( start ) ;
}
}
const definition = /** @type { Compiler .Attribute} */ ( element . attributes . splice ( index , 1 ) [ 0 ] ) ;
const definition = /** @type { AST .Attribute} */ ( element . attributes . splice ( index , 1 ) [ 0 ] ) ;
if ( definition . value === true ) {
if ( definition . value === true ) {
e . svelte _element _missing _this ( definition ) ;
e . svelte _element _missing _this ( definition ) ;
@ -241,9 +241,7 @@ export default function element(parser) {
// it would be much better to just error here, but we are preserving the existing buggy
// it would be much better to just error here, but we are preserving the existing buggy
// Svelte 4 behaviour out of an overabundance of caution regarding breaking changes.
// Svelte 4 behaviour out of an overabundance of caution regarding breaking changes.
// TODO in 6.0, error
// TODO in 6.0, error
const chunk = /** @type {Array<Compiler.ExpressionTag | Compiler.Text>} */ (
const chunk = /** @type {Array<AST.ExpressionTag | AST.Text>} */ ( definition . value ) [ 0 ] ;
definition . value
) [ 0 ] ;
element . tag =
element . tag =
chunk . type === 'Text'
chunk . type === 'Text'
? {
? {
@ -262,7 +260,7 @@ export default function element(parser) {
if ( is _top _level _script _or _style ) {
if ( is _top _level _script _or _style ) {
parser . eat ( '>' , true ) ;
parser . eat ( '>' , true ) ;
/** @type { Compiler .Comment | null} */
/** @type { AST .Comment | null} */
let prev _comment = null ;
let prev _comment = null ;
for ( let i = current . fragment . nodes . length - 1 ; i >= 0 ; i -- ) {
for ( let i = current . fragment . nodes . length - 1 ; i >= 0 ; i -- ) {
const node = current . fragment . nodes [ i ] ;
const node = current . fragment . nodes [ i ] ;
@ -329,7 +327,7 @@ export default function element(parser) {
const data = parser . read _until ( new RegExp ( ` </ ${ name } > ` ) ) ;
const data = parser . read _until ( new RegExp ( ` </ ${ name } > ` ) ) ;
const end = parser . index ;
const end = parser . index ;
/** @type { Compiler .Text} */
/** @type { AST .Text} */
const node = {
const node = {
start ,
start ,
end ,
end ,
@ -348,7 +346,7 @@ export default function element(parser) {
}
}
}
}
/** @param { Compiler. TemplateNode[]} stack */
/** @param { TemplateNode[]} stack */
function parent _is _head ( stack ) {
function parent _is _head ( stack ) {
let i = stack . length ;
let i = stack . length ;
while ( i -- ) {
while ( i -- ) {
@ -359,14 +357,14 @@ function parent_is_head(stack) {
return false ;
return false ;
}
}
/** @param { Compiler. TemplateNode[]} stack */
/** @param { TemplateNode[]} stack */
function parent _is _shadowroot _template ( stack ) {
function parent _is _shadowroot _template ( stack ) {
// https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#building_a_declarative_shadow_root
// https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#building_a_declarative_shadow_root
let i = stack . length ;
let i = stack . length ;
while ( i -- ) {
while ( i -- ) {
if (
if (
stack [ i ] . type === 'RegularElement' &&
stack [ i ] . type === 'RegularElement' &&
/** @type { Compiler .RegularElement} */ ( stack [ i ] ) . attributes . some (
/** @type { AST .RegularElement} */ ( stack [ i ] ) . attributes . some (
( a ) => a . type === 'Attribute' && a . name === 'shadowrootmode'
( a ) => a . type === 'Attribute' && a . name === 'shadowrootmode'
)
)
) {
) {
@ -378,7 +376,7 @@ function parent_is_shadowroot_template(stack) {
/ * *
/ * *
* @ param { Parser } parser
* @ param { Parser } parser
* @ returns { Compiler . Attribute | null }
* @ returns { AST . Attribute | null }
* /
* /
function read _static _attribute ( parser ) {
function read _static _attribute ( parser ) {
const start = parser . index ;
const start = parser . index ;
@ -386,7 +384,7 @@ function read_static_attribute(parser) {
const name = parser . read _until ( regex _token _ending _character ) ;
const name = parser . read _until ( regex _token _ending _character ) ;
if ( ! name ) return null ;
if ( ! name ) return null ;
/** @type {true | Array< Compiler.Text | Compiler .ExpressionTag>} */
/** @type {true | Array< AST.Text | AST .ExpressionTag>} */
let value = true ;
let value = true ;
if ( parser . eat ( '=' ) ) {
if ( parser . eat ( '=' ) ) {
@ -424,7 +422,7 @@ function read_static_attribute(parser) {
/ * *
/ * *
* @ param { Parser } parser
* @ param { Parser } parser
* @ returns { Compiler. Attribute | Compiler . SpreadAttribute | Compiler . Directive | null }
* @ returns { AST. Attribute | AST . SpreadAttribute | Directive | null }
* /
* /
function read _attribute ( parser ) {
function read _attribute ( parser ) {
const start = parser . index ;
const start = parser . index ;
@ -438,7 +436,7 @@ function read_attribute(parser) {
parser . allow _whitespace ( ) ;
parser . allow _whitespace ( ) ;
parser . eat ( '}' , true ) ;
parser . eat ( '}' , true ) ;
/** @type { Compiler .SpreadAttribute} */
/** @type { AST .SpreadAttribute} */
const spread = {
const spread = {
type : 'SpreadAttribute' ,
type : 'SpreadAttribute' ,
start ,
start ,
@ -462,7 +460,7 @@ function read_attribute(parser) {
parser . allow _whitespace ( ) ;
parser . allow _whitespace ( ) ;
parser . eat ( '}' , true ) ;
parser . eat ( '}' , true ) ;
/** @type { Compiler .ExpressionTag} */
/** @type { AST .ExpressionTag} */
const expression = {
const expression = {
type : 'ExpressionTag' ,
type : 'ExpressionTag' ,
start : value _start ,
start : value _start ,
@ -493,7 +491,7 @@ function read_attribute(parser) {
const colon _index = name . indexOf ( ':' ) ;
const colon _index = name . indexOf ( ':' ) ;
const type = colon _index !== - 1 && get _directive _type ( name . slice ( 0 , colon _index ) ) ;
const type = colon _index !== - 1 && get _directive _type ( name . slice ( 0 , colon _index ) ) ;
/** @type {true | Compiler.ExpressionTag | Array<Compiler.Text | Compiler .ExpressionTag>} */
/** @type {true | AST.ExpressionTag | Array<AST.Text | AST .ExpressionTag>} */
let value = true ;
let value = true ;
if ( parser . eat ( '=' ) ) {
if ( parser . eat ( '=' ) ) {
parser . allow _whitespace ( ) ;
parser . allow _whitespace ( ) ;
@ -542,7 +540,7 @@ function read_attribute(parser) {
}
}
}
}
/** @type { Compiler. Directive} */
/** @type { Directive} */
// @ts-expect-error TODO can't figure out this error
// @ts-expect-error TODO can't figure out this error
const directive = {
const directive = {
start ,
start ,
@ -599,7 +597,7 @@ function get_directive_type(name) {
/ * *
/ * *
* @ param { Parser } parser
* @ param { Parser } parser
* @ return { Compiler. ExpressionTag | Array < Compiler . ExpressionTag | Compiler . Text > }
* @ return { AST. ExpressionTag | Array < AST . ExpressionTag | AST . Text > }
* /
* /
function read _attribute _value ( parser ) {
function read _attribute _value ( parser ) {
const quote _mark = parser . eat ( "'" ) ? "'" : parser . eat ( '"' ) ? '"' : null ;
const quote _mark = parser . eat ( "'" ) ? "'" : parser . eat ( '"' ) ? '"' : null ;
@ -616,7 +614,7 @@ function read_attribute_value(parser) {
] ;
] ;
}
}
/** @type {Array< Compiler.ExpressionTag | Compiler .Text>} */
/** @type {Array< AST.ExpressionTag | AST .Text>} */
let value ;
let value ;
try {
try {
value = read _sequence (
value = read _sequence (
@ -662,7 +660,7 @@ function read_attribute_value(parser) {
* @ returns { any [ ] }
* @ returns { any [ ] }
* /
* /
function read _sequence ( parser , done , location ) {
function read _sequence ( parser , done , location ) {
/** @type { Compiler .Text} */
/** @type { AST .Text} */
let current _chunk = {
let current _chunk = {
start : parser . index ,
start : parser . index ,
end : - 1 ,
end : - 1 ,
@ -672,7 +670,7 @@ function read_sequence(parser, done, location) {
parent : null
parent : null
} ;
} ;
/** @type {Array< Compiler.Text | Compiler .ExpressionTag>} */
/** @type {Array< AST.Text | AST .ExpressionTag>} */
const chunks = [ ] ;
const chunks = [ ] ;
/** @param {number} end */
/** @param {number} end */
@ -710,7 +708,7 @@ function read_sequence(parser, done, location) {
parser . allow _whitespace ( ) ;
parser . allow _whitespace ( ) ;
parser . eat ( '}' , true ) ;
parser . eat ( '}' , true ) ;
/** @type { Compiler .ExpressionTag} */
/** @type { AST .ExpressionTag} */
const chunk = {
const chunk = {
type : 'ExpressionTag' ,
type : 'ExpressionTag' ,
start : index ,
start : index ,