sdgluck / mewt

:seedling: Immutability in under one kilobyte

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Mewt"ing an object from another object can break immutability

sscotth opened this issue · comments

Should probably create a clone.

const a = ['foo']
const b = mewt(a)
a.push('bar')
// 2
console.log(b)
// Proxy {0: "foo", 1: "bar", length: 2}

This could be a pretty difficult one to solve especially if the object is deeply nested and/or has circular references... I was thinking mewt could freeze the input but that's not very nice since we modify it. Maybe it would be nice to just document not to keep references to the stuff you want to mewt? And then the behaviour would be similar to what Java does with it's Collections#unmodifiable*

That wouldn't be a complete solution with the current clone implementation I guess. This could still occur:

const foo = { bar: { x: 42 } }
const immutableFoo = mewt(foo)

foo.bar.x = 43 // We can still mutate the nested props of the mewted object
console.log(immutableFoo.bar.x) // :(

@sscotth I know I don't need to separate the object creation and the wrapping, but essentially this is what you did in the original question just with an array. Shallow cloning the object absolutely did not solve this issue in my opinion.

This works ok now:

const a = ['foo']
const b = mewt(a)
a.push('hi') // doesn't affect b

But can we call the result of a mewt truly immutable if you can still do something like this:

const a = [{ foo: bar }]
const b = mewt(a)
// we still mutate b since the property 0 is not accessed through the Proxy
a[0].bar = 'ooops!' 

Re-opening as I wonder if it would be possible to fix this issue within the 1kb limit. Maybe with some aggressive manual minification. I'm going to give it a go soon, would be interested to hear your ideas.

Had a go on #30, but need to think about how best to tackle nested calls to $set/$unset.

Closing as nested immutability is implemented.