@ -239,6 +239,18 @@ export function migrate(source, { filename, use_ts } = {}) {
insertion _point = state . props _insertion _point ;
insertion _point = state . props _insertion _point ;
/ * *
* @ param { "derived" | "props" | "bindable" } rune
* /
function check _rune _binding ( rune ) {
const has _rune _binding = ! ! state . scope . get ( rune ) ;
if ( has _rune _binding ) {
throw new MigrationError (
` migrating this component would require adding a \` $ ${ rune } \` but there's already a variable named ${ rune } `
) ;
}
}
if ( state . props . length > 0 || analysis . uses _rest _props || analysis . uses _props ) {
if ( state . props . length > 0 || analysis . uses _rest _props || analysis . uses _props ) {
const has _many _props = state . props . length > 3 ;
const has _many _props = state . props . length > 3 ;
const newline _separator = ` \n ${ indent } ${ indent } ` ;
const newline _separator = ` \n ${ indent } ${ indent } ` ;
@ -253,6 +265,7 @@ export function migrate(source, { filename, use_ts } = {}) {
let prop _str =
let prop _str =
prop . local === prop . exported ? prop . local : ` ${ prop . exported } : ${ prop . local } ` ;
prop . local === prop . exported ? prop . local : ` ${ prop . exported } : ${ prop . local } ` ;
if ( prop . bindable ) {
if ( prop . bindable ) {
check _rune _binding ( 'bindable' ) ;
prop _str += ` = $ bindable( ${ prop . init } ) ` ;
prop _str += ` = $ bindable( ${ prop . init } ) ` ;
} else if ( prop . init ) {
} else if ( prop . init ) {
prop _str += ` = ${ prop . init } ` ;
prop _str += ` = ${ prop . init } ` ;
@ -300,11 +313,13 @@ export function migrate(source, { filename, use_ts } = {}) {
if ( type ) {
if ( type ) {
props _declaration = ` ${ type } \n \n ${ indent } ${ props _declaration } ` ;
props _declaration = ` ${ type } \n \n ${ indent } ${ props _declaration } ` ;
}
}
check _rune _binding ( 'props' ) ;
props _declaration = ` ${ props _declaration } ${ type ? ` : ${ type _name } ` : '' } = $ props(); ` ;
props _declaration = ` ${ props _declaration } ${ type ? ` : ${ type _name } ` : '' } = $ props(); ` ;
} else {
} else {
if ( type ) {
if ( type ) {
props _declaration = ` ${ state . props . length > 0 ? ` ${ type } \n \n ${ indent } ` : '' } /** @type { ${ state . props . length > 0 ? type _name : '' } ${ analysis . uses _props || analysis . uses _rest _props ? ` ${ state . props . length > 0 ? ' & ' : '' } { [key: string]: any } ` : '' } } */ \n ${ indent } ${ props _declaration } ` ;
props _declaration = ` ${ state . props . length > 0 ? ` ${ type } \n \n ${ indent } ` : '' } /** @type { ${ state . props . length > 0 ? type _name : '' } ${ analysis . uses _props || analysis . uses _rest _props ? ` ${ state . props . length > 0 ? ' & ' : '' } { [key: string]: any } ` : '' } } */ \n ${ indent } ${ props _declaration } ` ;
}
}
check _rune _binding ( 'props' ) ;
props _declaration = ` ${ props _declaration } = $ props(); ` ;
props _declaration = ` ${ props _declaration } = $ props(); ` ;
}
}
@ -361,6 +376,7 @@ export function migrate(source, { filename, use_ts } = {}) {
: insertion _point ;
: insertion _point ;
if ( state . derived _components . size > 0 ) {
if ( state . derived _components . size > 0 ) {
check _rune _binding ( 'derived' ) ;
str . appendRight (
str . appendRight (
insertion _point ,
insertion _point ,
` \n ${ indent } ${ [ ... state . derived _components . entries ( ) ] . map ( ( [ init , name ] ) => ` const ${ name } = $ derived( ${ init } ); ` ) . join ( ` \n ${ indent } ` ) } \n `
` \n ${ indent } ${ [ ... state . derived _components . entries ( ) ] . map ( ( [ init , name ] ) => ` const ${ name } = $ derived( ${ init } ); ` ) . join ( ` \n ${ indent } ` ) } \n `
@ -368,6 +384,7 @@ export function migrate(source, { filename, use_ts } = {}) {
}
}
if ( state . derived _conflicting _slots . size > 0 ) {
if ( state . derived _conflicting _slots . size > 0 ) {
check _rune _binding ( 'derived' ) ;
str . appendRight (
str . appendRight (
insertion _point ,
insertion _point ,
` \n ${ indent } ${ [ ... state . derived _conflicting _slots . entries ( ) ] . map ( ( [ name , init ] ) => ` const ${ name } = $ derived( ${ init } ); ` ) . join ( ` \n ${ indent } ` ) } \n `
` \n ${ indent } ${ [ ... state . derived _conflicting _slots . entries ( ) ] . map ( ( [ name , init ] ) => ` const ${ name } = $ derived( ${ init } ); ` ) . join ( ` \n ${ indent } ` ) } \n `
@ -652,6 +669,19 @@ const instance_script = {
continue ;
continue ;
}
}
/ * *
*
* @ param { "state" | "derived" } rune
* /
function check _rune _binding ( rune ) {
const has _rune _binding = ! ! state . scope . get ( rune ) ;
if ( has _rune _binding ) {
throw new MigrationError (
` can't migrate \` ${ state . str . original . substring ( /** @type {number} */ ( node . start ) , node . end ) } \` to \` $ ${ rune } \` because there's a variable named ${ rune } `
) ;
}
}
// state
// state
if ( declarator . init ) {
if ( declarator . init ) {
let { start , end } = /** @type {{ start: number, end: number }} */ ( declarator . init ) ;
let { start , end } = /** @type {{ start: number, end: number }} */ ( declarator . init ) ;
@ -661,6 +691,8 @@ const instance_script = {
while ( state . str . original [ end - 1 ] !== ')' ) end += 1 ;
while ( state . str . original [ end - 1 ] !== ')' ) end += 1 ;
}
}
check _rune _binding ( 'state' ) ;
state . str . prependLeft ( start , '$state(' ) ;
state . str . prependLeft ( start , '$state(' ) ;
state . str . appendRight ( end , ')' ) ;
state . str . appendRight ( end , ')' ) ;
} else {
} else {
@ -755,6 +787,8 @@ const instance_script = {
}
}
}
}
check _rune _binding ( 'derived' ) ;
// Someone wrote a `$: { ... }` statement which we can turn into a `$derived`
// Someone wrote a `$: { ... }` statement which we can turn into a `$derived`
state . str . appendRight (
state . str . appendRight (
/** @type {number} */ ( declarator . id . typeAnnotation ? . end ? ? declarator . id . end ) ,
/** @type {number} */ ( declarator . id . typeAnnotation ? . end ? ? declarator . id . end ) ,
@ -795,6 +829,8 @@ const instance_script = {
}
}
}
}
} else {
} else {
check _rune _binding ( 'state' ) ;
state . str . prependLeft (
state . str . prependLeft (
/** @type {number} */ ( declarator . id . typeAnnotation ? . end ? ? declarator . id . end ) ,
/** @type {number} */ ( declarator . id . typeAnnotation ? . end ? ? declarator . id . end ) ,
' = $state('
' = $state('
@ -858,6 +894,18 @@ const instance_script = {
next ( ) ;
next ( ) ;
/ * *
* @ param { "state" | "derived" } rune
* /
function check _rune _binding ( rune ) {
const has _rune _binding = state . scope . get ( rune ) ;
if ( has _rune _binding ) {
throw new MigrationError (
` can't migrate \` $ : ${ state . str . original . substring ( /** @type {number} */ ( node . body . start ) , node . body . end ) } \` to \` $ ${ rune } \` because there's a variable named ${ rune } `
) ;
}
}
if (
if (
node . body . type === 'ExpressionStatement' &&
node . body . type === 'ExpressionStatement' &&
node . body . expression . type === 'AssignmentExpression'
node . body . expression . type === 'AssignmentExpression'
@ -878,6 +926,8 @@ const instance_script = {
node . body . expression . right
node . body . expression . right
) ;
) ;
check _rune _binding ( 'derived' ) ;
// $derived
// $derived
state . str . update (
state . str . update (
/** @type {number} */ ( node . start ) ,
/** @type {number} */ ( node . start ) ,
@ -902,6 +952,7 @@ const instance_script = {
} else {
} else {
for ( const binding of reassigned _bindings ) {
for ( const binding of reassigned _bindings ) {
if ( binding && ( ids . includes ( binding . node ) || expression _ids . length === 0 ) ) {
if ( binding && ( ids . includes ( binding . node ) || expression _ids . length === 0 ) ) {
check _rune _binding ( 'state' ) ;
const init =
const init =
binding . kind === 'state'
binding . kind === 'state'
? ' = $state()'
? ' = $state()'