| 69 | } |
| 70 | |
| 71 | export class TcbForLoopTrackTranslator extends TcbExpressionTranslator { |
| 72 | private allowedVariables: Set<Variable>; |
| 73 | |
| 74 | constructor( |
| 75 | tcb: Context, |
| 76 | scope: Scope, |
| 77 | private block: ForLoopBlock, |
| 78 | ) { |
| 79 | super(tcb, scope); |
| 80 | |
| 81 | // Tracking expressions are only allowed to read the `$index`, |
| 82 | // the item and properties off the component instance. |
| 83 | this.allowedVariables = new Set([block.item]); |
| 84 | for (const variable of block.contextVariables) { |
| 85 | if (variable.value === '$index') { |
| 86 | this.allowedVariables.add(variable); |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | protected override resolve(ast: AST): TcbExpr | null { |
| 92 | if ( |
| 93 | ast instanceof PropertyRead && |
| 94 | (ast.receiver instanceof ImplicitReceiver || ast.receiver instanceof ThisReceiver) |
| 95 | ) { |
| 96 | const target = this.tcb.boundTarget.getExpressionTarget(ast); |
| 97 | |
| 98 | if ( |
| 99 | target !== null && |
| 100 | (!(target instanceof Variable) || !this.allowedVariables.has(target)) |
| 101 | ) { |
| 102 | this.tcb.oobRecorder.illegalForLoopTrackAccess(this.tcb.id, this.block, ast); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | return super.resolve(ast); |
| 107 | } |
| 108 | } |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…