import MagicString from 'magic-string' ; import { Node } from 'estree-walker' ; import { ScopeStack , Scope } from '../utils/Scope' ; import { isObjectKey , isMember } from '../../utils/svelteAst' ; import { assignmentBindings } from '../../htmlxtojsx/nodes/binding' ; export function handleStore ( node , parent , str ) { const storename = node . name . slice ( 1 ) ; if ( parent . type == 'AssignmentExpression' && parent . left == node && parent . operator == '=' ) { const dollar = str . original . indexOf ( '$' , node . start ) ; str . remove ( dollar , dollar + 1 ) ; str . overwrite ( node . end , str . original . indexOf ( '=' , node . end ) + 1 , '.set(' ) ; str . appendLeft ( parent . end , ')' ) ; return ; } const operators = [ '+=' , '-=' , '*=' , '/=' , '%=' , '**=' , '<<=' , '>>=' , '>>>=' , '&=' , '^=' , '|=' ] ; if ( parent . type == 'AssignmentExpression' && parent . left == node && operators . includes ( parent . operator ) ) { const storename = node . name . slice ( 1 ) ; const operator = parent . operator . substring ( 0 , parent . operator . length - 1 ) ; str . overwrite ( parent . start , str . original . indexOf ( '=' , node . end ) + 1 , `${ storename }.set( $${ storename } ${ operator }` ) ; str . appendLeft ( parent . end , ')' ) ; return ; } if ( parent . type == 'UpdateExpression' ) { let simpleOperator ; if ( parent . operator === '++' ) { simpleOperator = '+' ; } if ( parent . operator === '--' ) { simpleOperator = '-' ; } if ( simpleOperator ) { const storename = node . name . slice ( 1 ) ; str . overwrite ( parent . start , parent . end , `${ storename }.set( $${ storename } ${ simpleOperator } 1)` ) ; } else { console . warn ( `Warning - unrecognized UpdateExpression operator ${ parent . operator }!
                This is an edge case unaccounted for in svelte2tsx, please file an issue:
                https://github.com/sveltejs/language-tools/issues/new/choose
                ` , str . original . slice ( parent . start , parent . end ) ) ; } return ; } const dollar = str . original . indexOf ( '$' , node . start ) ; if ( parent . type === 'Binding' && assignmentBindings . has ( parent . name ) ) { str . overwrite ( dollar , dollar + 1 , '__sveltets_1_store_get(' , { contentOnly : true } ) ; str . prependLeft ( node . end , `), $${ storename }` ) ; return ; } str . overwrite ( dollar , dollar + 1 , '(__sveltets_1_store_get(' , { contentOnly : true } ) ; str . prependLeft ( node . end , `), $${ storename })` ) ; } type PendingStoreResolution < T > = { node : T ; parent : T ; scope : Scope ; } ; const reservedNames = new Set ( [ '$$props' , '$$restProps' , '$$slots' ] ) ; export class Stores { pendingStoreResolutions : Array < PendingStoreResolution < Node > > = [ ] ; constructor ( private scope , private str , private isDeclaration ) { } handleDirective ( node , str ) { if ( this . notAStore ( node . name ) || this . isDeclaration . value ) { return ; } const start = str . original . indexOf ( '$' , node . start ) ; const end = start + node . name . length ; this . pendingStoreResolutions . push ( { node : { type : 'Identifier' , start , end , name : node . name } , parent : { start : 0 , end : 0 , type : '' } , scope : this . scope . current } ) ; } handleIdentifier ( node , parent , prop ) { if ( this . notAStore ( node . name ) ) { return ; } if ( this . isDeclaration . value ) { if ( isObjectKey ( parent , prop ) ) { return ; } this . scope . current . declared . add ( node . name ) ; } else { if ( isMember ( parent , prop ) && ! parent . computed ) { return ; } if ( isObjectKey ( parent , prop ) ) { return ; } this . pendingStoreResolutions . push ( { node , parent , scope : this . scope . current } ) ; } } resolveStores ( ) { const unresolvedStores = this . pendingStoreResolutions . filter ( ( { node , scope } ) => { const name = node . name ; return ! scope . hasDefined ( name ) ; } ) ; unresolvedStores . forEach ( ( { node , parent } ) => handleStore ( node , parent , this . str ) ) ; return unresolvedStores . map ( ( { node } ) => node . name . slice ( 1 ) ) ; } private notAStore ( name ) { return name [ 0 ] !== '$' || reservedNames . has ( name ) ; } }