AUR0113

Error Message

AUR0113: Ast eval error: infinite loop detected. Increment operators should only be used in event handlers.

Description

This error occurs when a pre/post-increment (++) or pre/post-decrement (--) operator is used within a binding expression that is not part of an event handler (e.g., click.trigger, custom-event.trigger).

Cause

Aurelia's change detection mechanism evaluates binding expressions to update the view. Increment and decrement operators modify the variable they operate on (a side effect). If such an operator is used in a standard binding (like ${count++}, value.bind="items[index++]"), the evaluation itself changes the value, which can trigger another evaluation, leading to an infinite loop and this error.

These operators are considered safe only within event handler bindings (*.trigger, *.capture) because these expressions are typically executed only once in response to a user action or specific event, not as part of the regular change detection cycle.

Solution

  1. Move Logic to Event Handlers: If the increment/decrement is intended to happen in response to an event, ensure the expression is within an event binding (click.trigger="counter++", input.trigger="updateIndex(index++)").

  2. Use Methods in View Model: For non-event-related updates, perform the increment/decrement logic within a method in your view model and call that method if needed, or bind to a computed property that calculates the desired value without side effects.

  3. Avoid Side Effects in Bindings: Refrain from using expressions with side effects (like assignment =, ++, --) directly within bindings that are evaluated during change detection (interpolation ${}, *.bind, if.bind, repeat.for, etc.).

Example

<!-- Incorrect: Using ++ in interpolation (potential infinite loop) -->
<p>Count: ${ counter++ }</p>

<!-- Incorrect: Using ++ in a property binding -->
<input type="text" value.bind="values[currentIndex++]">

<!-- Correct: Using ++ within an event handler -->
<button click.trigger="counter++">Increment</button>
<button click.trigger="processItem(items[index++])">Process Next</button>

<!-- Correct: Using view model method for updates -->
<p>Count: ${ counter }</p>
<button click.trigger="incrementCounter()">Increment VM</button>

<!-- Correct: Binding to a computed value (no side effects in binding) -->
<p>Next Index: ${ nextIndex }</p>
// View Model Example
import { customElement } from 'aurelia';

@customElement({ /* ... */ })
export class MyComponent {
  counter = 0;
  items = ['A', 'B', 'C'];
  index = 0;

  incrementCounter() {
    this.counter++;
  }

  processItem(item: string) {
    console.log('Processing:', item);
    // 'this.index' has already been incremented if processItem(items[index++]) was used
  }

  // Computed property (getter) without side effects
  get nextIndex(): number {
    // Calculates without modifying 'index' directly in the getter
    return this.index + 1;
  }
}

Debugging Tips

  • Identify the binding expression that uses ++ or --.

  • Determine if the binding is an event handler or part of the regular rendering/update cycle.

  • If it's not an event handler, refactor the logic into the view model or ensure the operator is only used within an appropriate event trigger binding.

Last updated

Was this helpful?