-
-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Data cycle within ember-changeset triggers invalidation-after-set assertion #602
Comments
@ef4 You are totally right. I think this necessitates |
I don't know exactly what you mean, in terms of where you'd put a tracked object. My first reaction is that I wouldn't expect that to help because the problem is not a lack of tracking of deep mutations. |
To update Does this sound right? |
No, my point is that there's no need to ever delete a key. Validations all run together I think? So construct a whole new errors object, never reading from the old one. Alternatively, if you need to not rerun some validations, cache their answers but in a new untracked property. They you still always construct a new errors object each time, but the construction reads from the cache and not the old errors object. |
Great ideas! So there are two processes that happen with these "tracked" objects like
My inclination for num 1, Very interested in solving this. Just want to make sure I understand your position fully. |
@ef4 Does 1) make sense or am I misunderstanding something with regards to your point? (definitely value your feedback on this topic). |
I think you're misunderstanding. This code is already relying on assignment of All of that is good and I don't think you should change it. So no To solve (1):
This allows you to still incrementally update validators, while keeping |
Ok thx for the explanation! I think I have resolved the issue I was dealing with.
Fix coming this week. You are correct. Second, I incorrectly expanded your description of the error to this example that reads and writes. Accessors like Thanks for sticking with me on this! |
I don't think you can really guarantee which parts of your library will get called during render. It all depends how people use it. It looks like |
You are right and good point. Luckily, in these basic cases (non initial render), I'm not able to force an error in the dummy app or our tests. However, this is where I believe we would have to take a different path with the |
No, that's really not different. The state the user sets is purely an input to the changeset. You would only ever read from it, never write it. The resulting validation state is purely an output of the changeset. You would only ever write to it, never read from it.
Yes, please don't ever do this unless you're deliberately forcing a double render and know why you want a double render (measuring DOM is the typical reason). |
Also keep in mind that write-then-read is totally fine, it's only read-then-write that is a problem. (To think about why it's a problem, consider that reading a tracked property causes that tracked property to be an automatic dependency of the code you're running. If your code then changes that property, it just invalidated itself.) |
I truly want to solve this problem. However, whether it is my lack of experience or lack of creativity, I am having trouble seeing a path forward that doesn't result in a major change. I'll present my general observation first and then after go into some debugging steps. General ObservationsI believe we can partially fix the issue. But there exists a scenario that I don't think we can fix.
Overall, what we can do is solve the read-then-write for the Detailed stepsLets take your example with some of the guidance you have provided...
The previous steps don't explicitly illustrate read-then-write (rather write then read??). I'm just laying it out as I see it in while debugging as shown in the screenshots below. Screenshots in order to errorLet me know what you think! |
I think I may have been somewhat trolled here...We are accessing a property while trying to set it :( If I can find a way around this, perhaps our problem will be fully solved with a cache. Will update after some investigation. |
While validating, a changeset can consume its own
_errors
property before writing to it. This addon marks_errors
as tracked:https://github.com/poteto/ember-changeset/blob/072f062711df3f7e73ba81a887274002a3c98242/addon/index.js#L37
But if you read and then write a tracked property during rendering, Ember will throw the dreaded:
assertion.
Here is a tiny app that crashes at boot: ef4/--ember-changeset-bug-repro@90a2a00
Both the read and the write happen on this line:
https://github.com/validated-changeset/validated-changeset/blob/a23494a9a481fe639d4e00aaffdfc9e54ea50cce/src/index.ts#L795
First,
_deleteKey
's implementation consumesthis._errors
, and then we try to immediately assign to it.I suspect the same bug is also lurking in
rollbackInvalid()
, which does the same thing.The fix here is to make sure
_errors
is always only an output to your computation, never an input. Recompute the whole_errors
whenever it is needed without reference to the old value. And if you need caching, make caches that are not tracked.The text was updated successfully, but these errors were encountered: