immutable-js-oss/immutable-js

Using subsets of collection during mapping mutates the collection

Closed this issue · 1 comments

From @alechill on Wed, 08 Jan 2020 15:19:50 GMT

Using slice (or any subset creating methods, as they use slice under the surface) of a Collection.Indexed<V> during a map<MV>((v: V, i: number, collection: this): MV) removes items from the collection

This is presumably because map uses withMutations internally, however the docs do not warn agains using subsets in withMutations. Even if it did, a user is not to know using map unless they are aware of the internal implementation

Example

Immutable.List([0, 1]).map((v,i,c) => { 
    c.slice(0, i); 
    return v; 
})

Produces...

List {size: 2, _origin: 0, _capacity: 2, _level: 5, _root: null, …}
    size: 2
    _origin: 0
    _capacity: 2
    _level: 5
    _root: null
    _tail: VNode
        array: Array(1)
            0: 0
            length: 1
            __proto__: Array(0)
            ownerID: OwnerID {}
        __proto__: Object
        __ownerID: undefined
    __hash: undefined
    __altered: false
    __proto__: IndexedCollection

As you can see the size is still 2, but the contained nodes now only possesses 1 member

This is a trivial example with no real use for the slice, but a real life use case would be using values from all previous items in the collection to help map the new value.

For example mapping List(['usr', 'local', 'bin']) to List(['usr', 'usr/local', 'usr/local/bin'])

Copied from original issue: immutable-js#1757

Resolved in #7.