EDIT #2
It just occurred to me that maybe I’m not making myself clear on a particular point. I say this because a few times you’ve recommended setting debugger on a call to toString. The reason that’s not working is because the problem I’m calling out doesn’t involve a call to toString, but rather the adding of it to the object as a property.
So I wind up with an object that has toString on its prototype (as it should), and toString as a property of the object, like this:
const someObject = {
...
toString: function(value) {...} // tracked
...
}
someObject.prototype.toString = function(value) {...}
I can tell you that that’s nothing I’m doing. I’ve never before seen toString on an object twice, not to my recollection.
That might explain your puzzlement in the question to me earlier: “How did you get toString to be tracked?”
EDIT #1
You asked me earlier how I got toString to track. Actually, I didn’t. I have no idea how it’s happening. I’m not doing anything with toString anywhere.
Perhaps what follows will help…
ORIGINAL
@bigopon I tried your suggestion concerning toString() and I didn’t get anywhere with it (but it was a good thought).
The problem surfaced again in a different context, which is great because now I have a basis for comparison. It occurs now both in the context of my validation framework and in a rewrite I’m working on of a list component. Both of them involve bindables that are initialized to a plain object, and where in the view and/or a computed property, I use bracket notation to access the value of a property.
I can make the following statement as a sort of premise:
In those cases where a bindable is a plain object initialized to {},and the object is used in a computed property, and the property does not exist, the bindable will pick up the following properties:

where toString is not only on the prototype, but also on the object itself such that Object.keys(someObject).length === 0 and isEmpty(someObject) are both false (isEmpty taken from lodash).
That explains in an earlier post why the problem was found in this computed on my model:
@computed((model) => model.validation, { deep: true })
get hasValidationErrors() {
return Object.keys(this.validation)?.some((_prop) => this.validation[_prop]?.isValid === false);
}
I do believe it is this that’s causing the problem (perhaps confusing Aurelia’s tracking system):
this.validation[_prop]?.isValid
I say that because I have a very similar scenario in my handling of list selections:
get isSelected() {
return this.selected[this.item.id] ?? false;
}
where selected is also a bindable plain object initialized to {}.