Skip to content

multiMerge will *overwrite* key on iOS for '{}' #1046

Closed
@irisjae

Description

@irisjae

What happened?

According to documentation, the function of multiMerge is Multiple merging of existing and new values in a batch. Assumes that values are stringified JSON. Once completed, invokes callback with errors (if any).

One expects that the empty object {} is the identity of the operation of merging objects, and that merging the JSON-ified object "{}" into any value that is already an object will produce no effect.

This is the case on Android and not the case on iOS (tested with 1.19.3). The following snippet reproduces this, producing '{ "x": 1 }' for key "a" on Android, and producing '{}' on iOS.

let { default: { multiMerge, getAllKeys, multiGet } } = require ('@react-native-async-storage/async-storage')

Promise .resolve ()
.then (_ => multiMerge ([ [ 'a', '{ "x": 1 }' ] ] ))
.then (_ => multiMerge ([ [ 'a', '{}' ] ] ))
.then (_ => getAllKeys ())
.then (keys => multiGet (keys))
.then (entries => Object .fromEntries (entries))
.then (result => console .log (result))

The bug is caused by this line

if (RCTMergeRecursive(mergedVal, RCTJSONParse(entry[1], &jsonError))) {
Presumably, the line is intended to overwrite the previous value if the provided input is not an object (i.e. not mergeable). What is actually specified is overwriting of the previous value if the provided input has no keys, which unfortunately produces this bug. The corresponding implementation in Android properly (it seems) merges the values instead, and handles the case correctly.

Version

1.19.3

What platforms are you seeing this issue on?

  • Android
  • iOS
  • macOS
  • Windows
  • web

System Information

.

Steps to Reproduce

Provided above

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingreleased

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions