@@ -91,6 +91,7 @@ export class Scope {
91
91
const binding = {
92
92
node,
93
93
references : [ ] ,
94
+ referenced_in_template : false ,
94
95
legacy_dependencies : [ ] ,
95
96
initial,
96
97
mutated : false ,
@@ -168,20 +169,22 @@ export class Scope {
168
169
/**
169
170
* @param {import('estree').Identifier } node
170
171
* @param {import('#compiler').SvelteNode[] } path
172
+ * @param {boolean } is_template
171
173
*/
172
- reference ( node , path ) {
174
+ reference ( node , path , is_template ) {
173
175
let references = this . references . get ( node . name ) ;
174
176
if ( ! references ) this . references . set ( node . name , ( references = [ ] ) ) ;
175
177
176
178
references . push ( { node, path } ) ;
177
179
178
- const declaration = this . declarations . get ( node . name ) ;
179
- if ( declaration ) {
180
- declaration . references . push ( { node, path } ) ;
180
+ const binding = this . declarations . get ( node . name ) ;
181
+ if ( binding ) {
182
+ if ( is_template ) binding . referenced_in_template = true ;
183
+ binding . references . push ( { node, path } ) ;
181
184
} else if ( this . #parent) {
182
- this . #parent. reference ( node , path ) ;
185
+ this . #parent. reference ( node , path , is_template ) ;
183
186
} else {
184
- // no declaration was found, and this is the top level scope,
187
+ // no binding was found, and this is the top level scope,
185
188
// which means this is a global
186
189
this . root . conflicts . add ( node . name ) ;
187
190
}
@@ -214,10 +217,11 @@ export class ScopeRoot {
214
217
* @param {import('#compiler').SvelteNode } ast
215
218
* @param {ScopeRoot } root
216
219
* @param {boolean } allow_reactive_declarations
220
+ * @param {boolean } is_template
217
221
* @param {Scope | null } parent
218
222
*/
219
- export function create_scopes ( ast , root , allow_reactive_declarations , parent ) {
220
- /** @typedef {{ scope: Scope } } State */
223
+ export function create_scopes ( ast , root , allow_reactive_declarations , is_template , parent ) {
224
+ /** @typedef {{ scope: Scope, is_template: boolean } } State */
221
225
222
226
/**
223
227
* A map of node->associated scope. A node appearing in this map does not necessarily mean that it created a scope
@@ -228,9 +232,9 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
228
232
scopes . set ( ast , scope ) ;
229
233
230
234
/** @type {State } */
231
- const state = { scope } ;
235
+ const state = { scope, is_template } ;
232
236
233
- /** @type {[Scope, { node: import('estree').Identifier; path: import('#compiler').SvelteNode[] }][] } */
237
+ /** @type {[Scope, { node: import('estree').Identifier; path: import('#compiler').SvelteNode[]; is_template: boolean }][] } */
234
238
const references = [ ] ;
235
239
236
240
/** @type {[Scope, import('estree').Pattern | import('estree').MemberExpression][] } */
@@ -261,7 +265,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
261
265
const scope = state . scope . child ( true ) ;
262
266
scopes . set ( node , scope ) ;
263
267
264
- next ( { scope } ) ;
268
+ next ( { ... state , scope } ) ;
265
269
} ;
266
270
267
271
/**
@@ -270,7 +274,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
270
274
const SvelteFragment = ( node , { state, next } ) => {
271
275
const scope = analyze_let_directives ( node , state . scope ) ;
272
276
scopes . set ( node , scope ) ;
273
- next ( { scope } ) ;
277
+ next ( { ... state , scope } ) ;
274
278
} ;
275
279
276
280
/**
@@ -316,7 +320,10 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
316
320
Identifier ( node , { path, state } ) {
317
321
const parent = path . at ( - 1 ) ;
318
322
if ( parent && is_reference ( node , /** @type {import('estree').Node } */ ( parent ) ) ) {
319
- references . push ( [ state . scope , { node, path : path . slice ( ) } ] ) ;
323
+ references . push ( [
324
+ state . scope ,
325
+ { node, path : path . slice ( ) , is_template : state . is_template }
326
+ ] ) ;
320
327
}
321
328
} ,
322
329
@@ -339,15 +346,15 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
339
346
}
340
347
}
341
348
342
- next ( { scope } ) ;
349
+ next ( { ... state , scope } ) ;
343
350
} ,
344
351
345
352
SvelteFragment,
346
353
SvelteElement : SvelteFragment ,
347
354
RegularElement : SvelteFragment ,
348
355
349
356
Component ( node , { state, visit, path } ) {
350
- state . scope . reference ( b . id ( node . name ) , path ) ;
357
+ state . scope . reference ( b . id ( node . name ) , path , false ) ;
351
358
352
359
// let:x from the default slot is a weird one:
353
360
// Its scope only applies to children that are not slots themselves.
@@ -371,7 +378,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
371
378
} else if ( child . type === 'SnippetBlock' ) {
372
379
visit ( child ) ;
373
380
} else {
374
- visit ( child , { scope } ) ;
381
+ visit ( child , { ... state , scope } ) ;
375
382
}
376
383
}
377
384
} ,
@@ -405,7 +412,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
405
412
if ( node . id ) scope . declare ( node . id , 'normal' , 'function' ) ;
406
413
407
414
add_params ( scope , node . params ) ;
408
- next ( { scope } ) ;
415
+ next ( { scope, is_template : false } ) ;
409
416
} ,
410
417
411
418
FunctionDeclaration ( node , { state, next } ) {
@@ -415,15 +422,15 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
415
422
scopes . set ( node , scope ) ;
416
423
417
424
add_params ( scope , node . params ) ;
418
- next ( { scope } ) ;
425
+ next ( { scope, is_template : false } ) ;
419
426
} ,
420
427
421
428
ArrowFunctionExpression ( node , { state, next } ) {
422
429
const scope = state . scope . child ( ) ;
423
430
scopes . set ( node , scope ) ;
424
431
425
432
add_params ( scope , node . params ) ;
426
- next ( { scope } ) ;
433
+ next ( { scope, is_template : false } ) ;
427
434
} ,
428
435
429
436
ForStatement : create_block_scope ,
@@ -468,7 +475,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
468
475
state . scope . declare ( id , 'normal' , 'let' ) ;
469
476
}
470
477
471
- next ( { scope } ) ;
478
+ next ( { ... state , scope } ) ;
472
479
} else {
473
480
next ( ) ;
474
481
}
@@ -506,13 +513,13 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
506
513
( node . key . type !== 'Identifier' || ! node . index || node . key . name !== node . index ) ;
507
514
scope . declare ( b . id ( node . index ) , is_keyed ? 'derived' : 'normal' , 'const' ) ;
508
515
}
509
- if ( node . key ) visit ( node . key , { scope } ) ;
516
+ if ( node . key ) visit ( node . key , { ... state , scope } ) ;
510
517
511
518
// children
512
519
for ( const child of node . body . nodes ) {
513
- visit ( child , { scope } ) ;
520
+ visit ( child , { ... state , scope } ) ;
514
521
}
515
- if ( node . fallback ) visit ( node . fallback , { scope } ) ;
522
+ if ( node . fallback ) visit ( node . fallback , { ... state , scope } ) ;
516
523
517
524
// Check if inner scope shadows something from outer scope.
518
525
// This is necessary because we need access to the array expression of the each block
@@ -579,13 +586,13 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
579
586
}
580
587
}
581
588
582
- context . next ( { scope : child_scope } ) ;
589
+ context . next ( { ... state , scope : child_scope } ) ;
583
590
} ,
584
591
585
592
Fragment : ( node , context ) => {
586
593
const scope = context . state . scope . child ( node . transparent ) ;
587
594
scopes . set ( node , scope ) ;
588
- context . next ( { scope } ) ;
595
+ context . next ( { ... state , scope } ) ;
589
596
} ,
590
597
591
598
BindDirective ( node , context ) {
@@ -622,8 +629,8 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
622
629
623
630
// we do this after the fact, so that we don't need to worry
624
631
// about encountering references before their declarations
625
- for ( const [ scope , { node, path } ] of references ) {
626
- scope . reference ( node , path ) ;
632
+ for ( const [ scope , { node, path, is_template } ] of references ) {
633
+ scope . reference ( node , path , is_template ) ;
627
634
}
628
635
629
636
for ( const [ scope , node ] of updates ) {
0 commit comments