Ian, this can happen in the on_field_changed event handler when you change the value of some field.
This change in its turn generates the on_field_changed event that again changes some field and so on.
To prevent this from happening, it is better to use conditions on fields that have changed, for example:
function on_field_changed(field, lookup_item) {
let item = field.owner;
if (field.field_name === 'quantity' || field.field_name === 'unitprice') {
item.amount.value = item.round(item.quantity.value * item.unitprice.value, 2);
item.tax.value = item.round(item.amount.value * item.owner.taxrate.value / 100, 2);
item.total.value = item.amount.value + item.tax.value;
}
}
or the following algorithm can be used:
let calculating;
function on_field_changed(field, lookup_item) {
if (!calculating) {
calculating = true;
try {
// some calculations
}
finally {
calculating = false;
}
}
}