Skip to content
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

Fix incorrect mutation-after-consumption assertions for Array push and unshift #397

Merged
merged 2 commits into from
Jan 30, 2023

Conversation

chriskrycho
Copy link
Collaborator

For these methods, Array itself immediately gets the .length to return after invoking them. Thus, if we are reading .length, it may be a normal user-triggered read, or it may be a read triggered by Array itself. In the latter case, it is because we have just done .push() or .unshift(); in that case it is safe not to treat reading .length as a read operation, since calling .push() or .unshift() cannot otherwise be part of a "read" operation safely, and if done during an existing read (e.g. if the user has already checked .length prior to this), that will still trigger the assertion.

This PR:

  • Introduces a simple failing test. Simply doing a .push() or .unshift() call after creating the Array during construction of a component is enough to trigger the issue.

  • Introduces a flag, which the proxy's get() sets to true when calling .push() or .unshift(), and then clear it during the immediately-following .length check.

Fixes #29.

… bug

Simply doing a `.push()` or `.unshift()` call after creating the Array
during construction of a component is enough to trigger the issue. This
will be red in CI; the follow-on commit will fix it.
For these methods, `Array` itself immediately gets the `.length` to
return after invoking them. Thus, if we are reading `.length`, it may
be a normal user-triggered read, or it may be a read triggered by Array
itself. In the latter case, it is because we have just done `.push()`
or `.unshift()`; in that case it is safe *not* to treat reading
`.length` as a *read* operation, since calling `.push()` or
`.unshift()` cannot otherwise be part of a "read" operation safely, and
if done during an *existing* read (e.g. if the user has already checked
`.length` *prior* to this), that will still trigger the assertion.

Accordingly, set the new flag to `true` when calling `.push()` or
`.unshift()`, and then clear it during the immediately-following
`.length` check.
@chriskrycho
Copy link
Collaborator Author

Looks like we'll have to fix up CI first (separately!) but it does in fact work!

@chriskrycho chriskrycho added the bug Something isn't working label Jan 26, 2023
@chriskrycho chriskrycho merged commit e40a91a into master Jan 30, 2023
@chriskrycho chriskrycho deleted the fix-push-unshift branch January 30, 2023 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TrackedArray.push dirties and consumes the collection tag
1 participant