@@ -59,7 +59,8 @@ export class Binding {
5959
6060 mutated = false ;
6161 reassigned = false ;
62-
62+ read = false ;
63+ has_store_sub = false ;
6364 /**
6465 *
6566 * @param {Scope } scope
@@ -310,7 +311,7 @@ export class ScopeRoot {
310311 * @param {Scope | null } parent
311312 */
312313export function create_scopes ( ast , root , allow_reactive_declarations , parent ) {
313- /** @typedef {{ scope: Scope } } State */
314+ /** @typedef {{ scope: Scope, reading: boolean } } State */
314315
315316 /**
316317 * A map of node->associated scope. A node appearing in this map does not necessarily mean that it created a scope
@@ -321,14 +322,16 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
321322 scopes . set ( ast , scope ) ;
322323
323324 /** @type {State } */
324- const state = { scope } ;
325+ const state = { scope, reading : true } ;
325326
326- /** @type {[Scope, { node: Identifier; path: AST.SvelteNode[] }][] } */
327+ /** @type {[Scope, { node: Identifier; path: AST.SvelteNode[] }, boolean ][] } */
327328 const references = [ ] ;
328329
329330 /** @type {[Scope, Pattern | MemberExpression][] } */
330331 const updates = [ ] ;
331332
333+ /** @type {[Scope, Pattern | MemberExpression][] } */
334+ const read_updates = [ ] ;
332335 /**
333336 * An array of reactive declarations, i.e. the `a` in `$: a = b * 2`
334337 * @type {Identifier[] }
@@ -354,7 +357,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
354357 const scope = state . scope . child ( true ) ;
355358 scopes . set ( node , scope ) ;
356359
357- next ( { scope } ) ;
360+ next ( { scope, reading : state . reading } ) ;
358361 } ;
359362
360363 /**
@@ -363,7 +366,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
363366 const SvelteFragment = ( node , { state, next } ) => {
364367 const scope = state . scope . child ( ) ;
365368 scopes . set ( node , scope ) ;
366- next ( { scope } ) ;
369+ next ( { scope, reading : state . reading } ) ;
367370 } ;
368371
369372 /**
@@ -380,7 +383,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
380383
381384 const default_state = determine_slot ( node )
382385 ? context . state
383- : { scope : node . metadata . scopes . default } ;
386+ : { scope : node . metadata . scopes . default , reading : true } ;
384387
385388 for ( const attribute of node . attributes ) {
386389 if ( attribute . type === 'LetDirective' ) {
@@ -399,7 +402,8 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
399402 node . metadata . scopes [ slot_name ] = context . state . scope . child ( ) ;
400403
401404 state = {
402- scope : node . metadata . scopes [ slot_name ]
405+ scope : node . metadata . scopes [ slot_name ] ,
406+ reading : true
403407 } ;
404408 }
405409
@@ -430,10 +434,10 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
430434 // TODO -> once migration script is gone we can remove this check
431435 ! parent . type . startsWith ( 'TS' )
432436 ) {
433- references . push ( [ state . scope , { node, path : path . slice ( ) } ] ) ;
437+ references . push ( [ state . scope , { node, path : path . slice ( ) } , state . reading ] ) ;
434438 }
435439 } ,
436- LabeledStatement ( node , { path, next } ) {
440+ LabeledStatement ( node , { state , path, next } ) {
437441 if ( path . length > 1 || ! allow_reactive_declarations ) return next ( ) ;
438442 if ( node . label . name !== '$' ) return next ( ) ;
439443
@@ -452,7 +456,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
452456 }
453457 }
454458
455- next ( { scope } ) ;
459+ next ( { scope, reading : state . reading } ) ;
456460 } ,
457461
458462 SvelteFragment,
@@ -495,13 +499,22 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
495499 SvelteComponent : Component ,
496500
497501 // updates
498- AssignmentExpression ( node , { state, next } ) {
502+ AssignmentExpression ( node , { state, next, visit } ) {
499503 updates . push ( [ state . scope , node . left ] ) ;
500- next ( ) ;
504+ let reading = state . reading ;
505+ if ( node . operator !== '=' ) {
506+ reading = true ;
507+ } else {
508+ reading = false ;
509+ }
510+ visit ( node . left , { ...state , reading } ) ;
511+ visit ( node . right , state ) ;
501512 } ,
502513
503514 UpdateExpression ( node , { state, next } ) {
504515 updates . push ( [ state . scope , /** @type {Identifier | MemberExpression } */ ( node . argument ) ] ) ;
516+ //@ts -ignore
517+ read_updates . push ( updates . at ( - 1 ) ) ;
505518 next ( ) ;
506519 } ,
507520
@@ -518,7 +531,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
518531 if ( node . id ) scope . declare ( node . id , 'normal' , 'function' ) ;
519532
520533 add_params ( scope , node . params ) ;
521- next ( { scope } ) ;
534+ next ( { scope, reading : state . reading } ) ;
522535 } ,
523536
524537 FunctionDeclaration ( node , { state, next } ) {
@@ -528,15 +541,15 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
528541 scopes . set ( node , scope ) ;
529542
530543 add_params ( scope , node . params ) ;
531- next ( { scope } ) ;
544+ next ( { scope, reading : state . reading } ) ;
532545 } ,
533546
534547 ArrowFunctionExpression ( node , { state, next } ) {
535548 const scope = state . scope . child ( ) ;
536549 scopes . set ( node , scope ) ;
537550
538551 add_params ( scope , node . params ) ;
539- next ( { scope } ) ;
552+ next ( { scope, reading : state . reading } ) ;
540553 } ,
541554
542555 ForStatement : create_block_scope ,
@@ -593,7 +606,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
593606 scope . declare ( id , 'normal' , 'let' ) ;
594607 }
595608
596- next ( { scope } ) ;
609+ next ( { scope, reading : state . reading } ) ;
597610 } else {
598611 next ( ) ;
599612 }
@@ -631,7 +644,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
631644 }
632645
633646 // Visit to pick up references from default initializers
634- visit ( node . context , { scope } ) ;
647+ visit ( node . context , { scope, reading : state . reading } ) ;
635648 }
636649
637650 if ( node . index ) {
@@ -640,13 +653,13 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
640653 ( node . key . type !== 'Identifier' || ! node . index || node . key . name !== node . index ) ;
641654 scope . declare ( b . id ( node . index ) , is_keyed ? 'template' : 'normal' , 'const' , node ) ;
642655 }
643- if ( node . key ) visit ( node . key , { scope } ) ;
656+ if ( node . key ) visit ( node . key , { scope, reading : state . reading } ) ;
644657
645658 // children
646659 for ( const child of node . body . nodes ) {
647- visit ( child , { scope } ) ;
660+ visit ( child , { scope, reading : state . reading } ) ;
648661 }
649- if ( node . fallback ) visit ( node . fallback , { scope } ) ;
662+ if ( node . fallback ) visit ( node . fallback , { scope, reading : state . reading } ) ;
650663
651664 node . metadata = {
652665 expression : create_expression_metadata ( ) ,
@@ -671,7 +684,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
671684 const then_scope = /** @type {Scope } */ ( scopes . get ( node . then ) ) ;
672685 const value_scope = context . state . scope . child ( ) ;
673686 scopes . set ( node . value , value_scope ) ;
674- context . visit ( node . value , { scope : value_scope } ) ;
687+ context . visit ( node . value , { scope : value_scope , reading : state . reading } ) ;
675688 for ( const id of extract_identifiers ( node . value ) ) {
676689 then_scope . declare ( id , 'template' , 'const' ) ;
677690 value_scope . declare ( id , 'normal' , 'const' ) ;
@@ -685,7 +698,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
685698 const catch_scope = /** @type {Scope } */ ( scopes . get ( node . catch ) ) ;
686699 const error_scope = context . state . scope . child ( ) ;
687700 scopes . set ( node . error , error_scope ) ;
688- context . visit ( node . error , { scope : error_scope } ) ;
701+ context . visit ( node . error , { scope : error_scope , reading : state . reading } ) ;
689702 for ( const id of extract_identifiers ( node . error ) ) {
690703 catch_scope . declare ( id , 'template' , 'const' ) ;
691704 error_scope . declare ( id , 'normal' , 'const' ) ;
@@ -709,13 +722,13 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
709722 }
710723 }
711724
712- context . next ( { scope : child_scope } ) ;
725+ context . next ( { scope : child_scope , reading : state . reading } ) ;
713726 } ,
714727
715728 Fragment : ( node , context ) => {
716729 const scope = context . state . scope . child ( node . metadata . transparent ) ;
717730 scopes . set ( node , scope ) ;
718- context . next ( { scope } ) ;
731+ context . next ( { scope, reading : state . reading } ) ;
719732 } ,
720733
721734 BindDirective ( node , context ) {
@@ -753,8 +766,12 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
753766
754767 // we do this after the fact, so that we don't need to worry
755768 // about encountering references before their declarations
756- for ( const [ scope , { node, path } ] of references ) {
769+ for ( const [ scope , { node, path } , reading ] of references ) {
757770 scope . reference ( node , path ) ;
771+ let binding = scope . get ( node . name ) ;
772+ if ( binding && binding . node !== node && reading ) {
773+ binding . read = true ;
774+ }
758775 }
759776
760777 for ( const [ scope , node ] of updates ) {
0 commit comments