Repository navigation
Conversation
* Validate the whole pulled changeset before applying any of it applyRemoteChanges validated records one by one while preparing them, so a malformed record (or one id listed in both updated and deleted) threw after earlier records had already been prepared. Those records kept their pending state and mutated raw in the cache, so later update() calls on them failed until the app restarted. The changeset is now checked up front: table shape, record shape (string id, no _status/_changed, no __proto__ key), string deleted ids, and duplicate ids across created/updated/deleted. Unknown tables are still skipped for forward-compatibility. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Validate the same tables that are applied, and add a changelog entry getAllRecordsToApply enumerates tables with for-in (through filterObj), which includes inherited keys, while validation used Object.keys. Validation now enumerates the same way, so no applied table skips it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Require own enumerable created/updated/deleted arrays Table changes are copied with object spread when applied, which drops inherited and non-enumerable keys. Changes whose arrays were only inherited passed validation and then failed after earlier tables were prepared. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 2, 2026
|
Hi @joker-777, thank you, that's a great catch on the half-prepared records! I maintain NitromelonDB, a maintained fork of WatermelonDB (New Architecture, Nitro Modules). This applies there too: Our fork was rewritten in TypeScript (strict mode) to reduce the chance of bugs like this one slipping through, so I think the community would really benefit if you opened your PRs against it too. The code lives in If you don't have the time or would rather not, no worries at all, I'm happy to port it myself. Just let me know. Thanks a lot! |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Validates a pulled changeset in full before any record is prepared, so a bad pull fails with nothing touched.
Before, an invalid record halfway through a pull left the records before it prepared but never batched. They stayed in the record cache in that state, and
update()on them threw until the app restarted.Changes
created,updatedanddeletedarrays; every record has a stringidand no_status,_changedor__proto__; deleted ids are stringscreated,updatedanddeletedis rejected (for example, updated and deleted in the same pull)idis now rejected. Before, it was silently given a random idTests
New tests in
applyRemote.test.jscover a bad second table, duplicate ids, malformed tables and malformed ids. Each checks that a record from earlier in the pull is unchanged and can still be updated. On master they fail withrecord.prepareUpdate was called on mock_projects#pSynced but wasn't sent to batch().Verification
sqlite-nodesuite was left out because better-sqlite3 does not build on the host's Node; this change does not touch the adapters).flow checkis clean, and ESLint is clean on the changed filesapplyRemote.jsand its tests in separate places. They merge into master together without conflicts, and Jest passes on the result🤖 Generated with Claude Code