Skip to content

fix: track Map upserts and protect frozen Maps - #1348

Open
Marve10s wants to merge 1 commit into
immerjs:mainfrom
Marve10s:fix/map-upsert-methods
Open

Marve10s wants to merge 1 commit into
immerjs:mainfrom
Marve10s:fix/map-upsert-methods

Conversation

@Marve10s

Copy link
Copy Markdown

Map#getOrInsert and Map#getOrInsertComputed currently bypass Immer's Map state. On a draft, they can return the fallback for an existing key and silently discard inserted entries. On a produced Map, they can mutate its contents even though the Map is frozen and ordinary set calls throw.

Draft Maps inherit these native methods, which read the empty native Map storage created by super() instead of Immer's tracked contents. This implements the methods through the existing draft operations and includes them in the frozen Map mutation guards. Each method is exposed only when the runtime supports it, so older runtimes keep their existing API.

For example, starting with new Map([['a', 1]]):

const next = produce(base, draft => {
  draft.getOrInsert('a', 9)
  draft.getOrInsert('b', 2)
})

Before, the existing-key call returns 9 and next contains only ['a', 1]. After, it returns 1 and next also contains ['b', 2]. Calling next.getOrInsert('c', 3) now rejects mutation consistently with next.set('c', 3).

The computed form preserves native callback validation and key handling, skips the callback for existing keys, and applies the callback result even if the callback inserted the same key. Returning existing values through the draft's get also preserves nested drafting.

The failure reproduces on Immer 11.2.9 and current main without external services. Set composition methods are outside this patch.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant