# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
Dates are formatted as YYYY-MM-DD.
## [Unreleased]
## [4.1.0] - 2022-05-23
- Accept Symbol as Map key. [#1859](https://github.com/immutable-js/immutable-js/pull/1859) by [jdeniau](https://github.com/jdeniau)
- Optimize contructors without arguments [#1887](https://github.com/immutable-js/immutable-js/pull/1887) by [marianoguerra](https://github.com/marianoguerra)
- Fix Flow removeIn types [#1902](https://github.com/immutable-js/immutable-js/pull/1902) by [nifgraup](https://github.com/nifgraup)
- Fix bug in Record.equals when comparing against Map [#1903](https://github.com/immutable-js/immutable-js/pull/1903) by [jmtoung](https://github.com/jmtoung)
## [4.0.0] - 2021-09-30
This release brings new functionality and many fixes.
1. [Key changes](#key-changes)
1. [Note for users of v4.0.0-rc.12](#note-for-users-of-v400-rc12)
1. [Breaking changes](#breaking)
1. [New](#new)
1. [Fixed](#fixed)
### Key changes
* New members have joined the team
* The project has been relicensed as MIT
* Better TypeScript and Flow type definitions
* A brand-new documentation lives at [immutable-js.com](https://immutable-js.com/) and can show multiple versions
* Behavior of `merge` and `mergeDeep` has changed
* `Iterable` is renamed to [Collection](https://immutable-js.com/docs/latest@main/Collection/)
* [Records](https://immutable-js.com/docs/latest@main/Record/) no longer extend from Collections
* All collection types now implement the [ES6 iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol)
* New methods:
* [toJSON()](https://immutable-js.com/docs/latest@main/Collection/#toJSON())
* [wasAltered()](https://immutable-js.com/docs/latest@main/Map/#wasAltered())
* [Collection.Indexed.zipAll()](https://immutable-js.com/docs/latest@main/Collection.Indexed#zipAll())
* [Map.deleteAll()](https://immutable-js.com/docs/latest@main/Map/#deleteAll())
Diff of changed API (click to expand)
```diff
+ Collection.[Symbol.iterator]
+ Collection.toJSON
+ Collection.update
+ Collection.Indexed.[Symbol.iterator]
+ Collection.Indexed.toJSON
+ Collection.Indexed.update
+ Collection.Indexed.zipAll
+ Collection.Keyed.[Symbol.iterator]
+ Collection.Keyed.toJSON
+ Collection.Keyed.update
+ Collection.Set.[Symbol.iterator]
+ Collection.Set.toJSON
+ Collection.Set.update
- Collection.size
- Collection.Indexed.size
- Collection.Keyed.size
- Collection.Set.size
+ List.[Symbol.iterator]
+ List.toJSON
+ List.wasAltered
+ List.zipAll
- List.mergeDeep
- List.mergeDeepWith
- List.mergeWith
+ Map.[Symbol.iterator]
+ Map.deleteAll
+ Map.toJSON
+ Map.wasAltered
+ OrderedMap.[Symbol.iterator]
+ OrderedMap.deleteAll
+ OrderedMap.toJSON
+ OrderedMap.wasAltered
+ OrderedSet.[Symbol.iterator]
+ OrderedSet.toJSON
+ OrderedSet.update
+ OrderedSet.wasAltered
+ OrderedSet.zip
+ OrderedSet.zipAll
+ OrderedSet.zipWith
+ Record.[Symbol.iterator]
+ Record.asImmutable
+ Record.asMutable
+ Record.clear
+ Record.delete
+ Record.deleteIn
+ Record.merge
+ Record.mergeDeep
+ Record.mergeDeepIn
+ Record.mergeDeepWith
+ Record.mergeIn
+ Record.mergeWith
+ Record.set
+ Record.setIn
+ Record.toJSON
+ Record.update
+ Record.updateIn
+ Record.wasAltered
+ Record.withMutations
+ Record.Factory.displayName
- Record.butLast
- Record.concat
- Record.count
- Record.countBy
- Record.entries
- Record.entrySeq
- Record.every
- Record.filter
- Record.filterNot
- Record.find
- Record.findEntry
- Record.findKey
- Record.findLast
- Record.findLastEntry
- Record.findLastKey
- Record.first
- Record.flatMap
- Record.flatten
- Record.flip
- Record.forEach
- Record.groupBy
- Record.includes
- Record.isEmpty
- Record.isSubset
- Record.isSuperset
- Record.join
- Record.keyOf
- Record.keySeq
- Record.keys
- Record.last
- Record.lastKeyOf
- Record.map
- Record.mapEntries
- Record.mapKeys
- Record.max
- Record.maxBy
- Record.min
- Record.minBy
- Record.reduce
- Record.reduceRight
- Record.rest
- Record.reverse
- Record.skip
- Record.skipLast
- Record.skipUntil
- Record.skipWhile
- Record.slice
- Record.some
- Record.sort
- Record.sortBy
- Record.take
- Record.takeLast
- Record.takeUntil
- Record.takeWhile
- Record.toArray
- Record.toIndexedSeq
- Record.toKeyedSeq
- Record.toList
- Record.toMap
- Record.toOrderedMap
- Record.toOrderedSet
- Record.toSet
- Record.toSetSeq
- Record.toStack
- Record.valueSeq
- Record.values
+ Seq.[Symbol.iterator]
+ Seq.toJSON
+ Seq.update
+ Seq.Indexed.[Symbol.iterator]
+ Seq.Indexed.toJSON
+ Seq.Indexed.update
+ Seq.Indexed.zipAll
+ Seq.Keyed.[Symbol.iterator]
+ Seq.Keyed.toJSON
+ Seq.Keyed.update
+ Seq.Set.[Symbol.iterator]
+ Seq.Set.toJSON
+ Seq.Set.update
+ Set.[Symbol.iterator]
+ Set.toJSON
+ Set.update
+ Set.wasAltered
+ Stack.[Symbol.iterator]
+ Stack.toJSON
+ Stack.update
+ Stack.wasAltered
+ Stack.zipAll
+ ValueObject.equals
+ ValueObject.hashCode
- Iterable.*
- Iterable.Indexed.*
- Iterable.Keyed.*
- Iterable.Set.*
```
### Note for users of v4.0.0-rc.12
There were mostly bugfixes and improvements since RC 12. Upgrading should be painless for most users.
However, there is **one breaking change**: The behavior of `merge` and `mergeDeep` has changed. See below for details.
### BREAKING
#### [merge()](https://immutable-js.com/docs/latest@main/merge()/)
* No longer use value-equality within `merge()` ([#1391](https://github.com/immutable-js/immutable-js/pull/1391))
> This rectifies an inconsistent behavior between `x.merge(y)` and `x.mergeDeep(y)` where merge would
> use `===` on leaf values to determine return-self optimizations, while mergeDeep would use `is()`.
> This improves consistency across the library and avoids a possible performance pitfall.
* No longer deeply coerce argument to merge() ([#1339](https://github.com/immutable-js/immutable-js/pull/1339))
> Previously, the argument provided to `merge()` was deeply converted to Immutable collections via `fromJS()`.
> This was the only function in the library which calls `fromJS()` indirectly,
> and it was surprising and made it difficult to understand what the result of `merge()` would be.
> Now, the value provided to `merge()` is only shallowly converted to an Immutable collection, similar to
> related methods in the library. This may change the behavior of your calls to `merge()`.
#### [mergeDeep()](https://immutable-js.com/docs/latest@main/mergeDeep()/)
* Replace incompatible collections when merging nested data ([#1840](https://github.com/immutable-js/immutable-js/pull/1840))
> It will no longer merge lists of tuples into maps. For more information see
> [#1840](https://github.com/immutable-js/immutable-js/pull/1840) and the updated `mergeDeep()` documentation.
* Concat Lists when merging deeply ([#1344](https://github.com/immutable-js/immutable-js/pull/1344))
> Previously, calling `map.mergeDeep()` with a value containing a `List` would replace the values in the
> original List. This has always been confusing, and does not properly treat `List` as a monoid.
> Now, `List.merge` is simply an alias for `List.concat`, and `map.mergeDeep()` will concatenate deeply-found lists
> instead of replacing them.
#### [Seq](https://immutable-js.com/docs/latest@main/Seq/)
* Remove IteratorSequence. Do not attempt to detect iterators in `Seq()`. ([#1589](https://github.com/immutable-js/immutable-js/pull/1589))
> Iterables can still be provided to `Seq()`, and *most* Iterators are also
> Iterables, so this change should not affect the vast majority of uses.
> For more information, see PR #1589
* Remove `Seq.of()` (#1311, #1310)
> This method has been removed since it cannot be correctly typed. It's recommended to convert
> `Seq.of(1, 2, 3)` to `Seq([1, 2, 3])`.
#### [isImmutable()](https://immutable-js.com/docs/latest@main/isImmutable()/)
* `isImmutable()` now returns true for collections currently within a `withMutations()` call. ([#1374](https://github.com/immutable-js/immutable-js/pull/1374))
> Previously, `isImmutable()` did double-duty of both determining if a value was a Collection or Record
> from this library as well as if it was outside a `withMutations()` call.
> This latter case caused confusion and was rarely used.
#### [toArray()](https://immutable-js.com/docs/latest@main/Collection.Keyed#toArray())
* KeyedCollection.toArray() returns array of tuples. ([#1340](https://github.com/immutable-js/immutable-js/pull/1340))
> Previously, calling `toArray()` on a keyed collection (incl `Map` and `OrderedMap`) would
> discard keys and return an Array of values. This has always been confusing, and differs from `Array.from()`.
> Now, calling `toArray()` on a keyed collection will return an Array of `[key, value]` tuples, matching
> the behavior of `Array.from()`.
#### [concat()](https://immutable-js.com/docs/latest@main/List/#concat())
- `list.concat()` now has a slightly more efficient implementation and `map.concat()` is an alias for `map.merge()`. ([#1373](https://github.com/immutable-js/immutable-js/pull/1373))
> In rare cases, this may affect use of `map.concat()` which expected slightly different behavior from `map.merge()`.
#### [Collection](https://immutable-js.com/docs/latest@main/Collection/), formerly `Iterable`
* The `Iterable` class has been renamed to `Collection`, and `isIterable()` has been renamed to `isCollection()`.
Aliases with the existing names exist to make transitioning code easier.
#### [Record](https://immutable-js.com/docs/latest@main/Record/)
* Record is no longer an Immutable Collection type.
* Now `isCollection(myRecord)` returns `false` instead of `true`.
* The sequence API (such as `map`, `filter`, `forEach`) no longer exist on Records.
* `delete()` and `clear()` no longer exist on Records.
#### Other breaking changes
* **Potentially Breaking:** Improve hash speed and avoid collision for common values ([#1629](https://github.com/immutable-js/immutable-js/pull/1629))
> Causes some hash values to change, which could impact the order of iteration of values in some Maps
> (which are already advertised as unordered, but highlighting just to be safe)
* Node buffers no longer considered value-equal ([#1437](https://github.com/immutable-js/immutable-js/pull/1437))
* Plain Objects and Arrays are no longer considered opaque values ([#1369](https://github.com/immutable-js/immutable-js/pull/1369))
> This changes the behavior of a few common methods with respect to plain Objects and Arrays where these were
> previously considered opaque to `merge()` and `setIn()`, they now are treated as collections and can be merged
> into and updated (persistently). This offers an exciting alternative to small Lists and Records.
* The "predicate" functions, `isCollection`, `isKeyed`, `isIndexed`, `isAssociative` have been moved from `Iterable.` to the top level exports.
* The `toJSON()` method performs a shallow conversion (previously it was an alias for `toJS()`, which remains a deep conversion).
* Some minor implementation details have changed, which may require updates to libraries which deeply integrate with Immutable.js's private APIs.
* The Cursor API is officially deprecated. Use [immutable-cursor](https://github.com/redbadger/immutable-cursor) instead.
* **Potentially Breaking:** [TypeScript] Remove `Iterable` as tuple from Map constructor types ([#1626](https://github.com/immutable-js/immutable-js/pull/1626))
> Typescript allowed constructing a Map with a list of List instances, assuming each was a key, value pair.
> While this runtime behavior still works, this type led to more issues than it solved, so it has been removed.
> (Note, this may break previous v4 rcs, but is not a change against v3)
### New
* Update TypeScript and Flow definitions:
* The Flowtype and TypeScript type definitions have been completely rewritten with much higher quality and accuracy,
taking advantage of the latest features from both tools.
* Simplified TypeScript definition files to support all UMD use cases ([#1854](https://github.com/immutable-js/immutable-js/pull/1854))
* Support Typescript 3 ([#1593](https://github.com/immutable-js/immutable-js/pull/1593))
* Support Typescript strictNullChecks ([#1168](https://github.com/immutable-js/immutable-js/pull/1168))
* Flow types to be compatible with the latest version 0.160.0
* Enable flow strict ([#1580](https://github.com/immutable-js/immutable-js/pull/1580))
* Add "sideEffects: false" to package.json ([#1661](https://github.com/immutable-js/immutable-js/pull/1661))
* Use ES standard for iterator method reuse ([#1867](https://github.com/immutable-js/immutable-js/pull/1867))
* Generalize `fromJS()` and `Seq()` to support Sets ([#1865](https://github.com/immutable-js/immutable-js/pull/1865))
* Top level predicate functions ([#1600](https://github.com/immutable-js/immutable-js/pull/1600))
> New functions are exported from the `immutable` module:
> `isSeq()`, `isList()`, `isMap()`, `isOrderedMap()`, `isStack()`, `isSet()`, `isOrderedSet()`, and `isRecord()`.
* Improve performance of toJS ([#1581](https://github.com/immutable-js/immutable-js/pull/1581))
> Cursory test is >10% faster than both v3.8.2 and v4.0.0-rc.7,
> and corrects the regression since v4.0.0-rc.9.
* Added optional `notSetValue` in `first()` and `last()` ([#1556](https://github.com/immutable-js/immutable-js/pull/1556))
* Make `isArrayLike` check more precise to avoid false positives ([#1520](https://github.com/immutable-js/immutable-js/pull/1520))
* `map()` for List, Map, and Set returns itself for no-ops ([#1455](https://github.com/immutable-js/immutable-js/pull/1455)) (5726bd1)
* Hash functions as objects, allowing functions as values in collections ([#1485](https://github.com/immutable-js/immutable-js/pull/1485))
* Functional API for `get()`, `set()`, and more which support both Immutable.js collections and plain Objects and Arrays ([#1369](https://github.com/immutable-js/immutable-js/pull/1369))
* Relicensed as MIT ([#1320](https://github.com/immutable-js/immutable-js/pull/1320))
* Support for Transducers! ([ee9c68f1](https://github.com/immutable-js/immutable-js/commit/ee9c68f1d43da426498ee009ecea37aa2ef77cb8))
* Add new method, `zipAll()` ([#1195](https://github.com/immutable-js/immutable-js/pull/1195))
* Bundle and distribute an "es module" so Webpack and Rollup can use tree-shaking for smaller builds ([#1204](https://github.com/immutable-js/immutable-js/pull/1204))
* Warn instead of throw when `getIn()` has a bad path ([668f2236](https://github.com/immutable-js/immutable-js/commit/668f2236642c97bd4e7d8dfbf62311f497a6ac18))
* A new predicate function `isValueObject()` helps to detect objects which implement `equals()` and `hashCode()`,
and type definitions now define the interface `ValueObject` which you can implement in your own code to create objects which
behave as values and can be keys in Maps or entries in Sets.
* Using `fromJS()` with a "reviver" function now provides access to the key path to each translated value. ([#1118](https://github.com/immutable-js/immutable-js/pull/1118))
### Fixed
* Fix issue with IE11 and missing Symbol.iterator ([#1850](https://github.com/immutable-js/immutable-js/pull/1850))
* Fix ordered set with map ([#1663](https://github.com/immutable-js/immutable-js/pull/1663))
* Do not modify iter during List.map and Map.map ([#1649](https://github.com/immutable-js/immutable-js/pull/1649))
* Fix ordered map delete all ([#1777](https://github.com/immutable-js/immutable-js/pull/1777))
* Hash symbols as objects ([#1753](https://github.com/immutable-js/immutable-js/pull/1753))
* Fix returning a Record in merge() when Record is empty ([#1785](https://github.com/immutable-js/immutable-js/pull/1785))
* Fix for RC~12: Records from different factories aren't equal ([#1734](https://github.com/immutable-js/immutable-js/issues/1734))
* "too much recursion" error when creating a Record type from an instance of another Record ([#1690](https://github.com/immutable-js/immutable-js/pull/1690))
* Fix glob for npm format script on Windows ([#18](https://github.com/immutable-js-oss/immutable-js/pull/18))
* Remove deprecated cursor API ([#13](https://github.com/immutable-js-oss/immutable-js/issues/13))
* Add missing es exports ([#1740](https://github.com/immutable-js/immutable-js/pull/1740))
* Support nulls in genTypeDefData.js ([#185](https://github.com/immutable-js/immutable-js/pull/185))
* Support isPlainObj in IE11 and other esoteric parameters [f3a6d5ce](https://github.com/immutable-js/immutable-js/pull/1833/commits/f3a6d5ce75bb9d60b87074240838f5429e896b60)
* `Set.map` produces valid underlying map ([#1606](https://github.com/immutable-js/immutable-js/pull/1606))
* Support isPlainObj with `constructor` key ([#1627](https://github.com/immutable-js/immutable-js/pull/1627))
* `groupBy` no longer returns a mutable Map instance ([#1602](https://github.com/immutable-js/immutable-js/pull/1602))
* Fix issue where refs can recursively collide, corrupting `.size` ([#1598](https://github.com/immutable-js/immutable-js/pull/1598))
* Throw error in `mergeWith()` method if missing the required `merger` function ([#1543](https://github.com/immutable-js/immutable-js/pull/1543))
* Update `isPlainObj()` to workaround Safari bug and allow cross-realm values ([#1557](https://github.com/immutable-js/immutable-js/pull/1557))
* Fix missing "& T" to some methods in RecordInstance ([#1464](https://github.com/immutable-js/immutable-js/pull/1464))
* Make notSetValue optional for typed Records ([#1461](https://github.com/immutable-js/immutable-js/pull/1461)) (a1029bb)
* Export type of RecordInstance ([#1434](https://github.com/immutable-js/immutable-js/pull/1434))
* Fix Record `size` check in merge() ([#1521](https://github.com/immutable-js/immutable-js/pull/1521))
* Fix Map#concat being not defined ([#1402](https://github.com/immutable-js/immutable-js/pull/1402))
* `getIn()` no longer throws when encountering a missing path ([#1361](https://github.com/immutable-js/immutable-js/pull/1361))
* Do not throw when printing value that cannot be coerced to primitive ([#1334](https://github.com/immutable-js/immutable-js/pull/1334))
* Do not throw from hasIn ([#1319](https://github.com/immutable-js/immutable-js/pull/1319))
* Long hash codes no longer cause an infinite loop ([#1175](https://github.com/immutable-js/immutable-js/pull/1175))
* `slice()` which should return an empty set could return a full set or vice versa (#1245, #1287)
* Ensure empty slices do not throw when iterated ([#1220](https://github.com/immutable-js/immutable-js/pull/1220))
* Error during equals check on Record with undefined or null ([#1208](https://github.com/immutable-js/immutable-js/pull/1208))
* Fix size of count() after filtering or flattening ([#1171](https://github.com/immutable-js/immutable-js/pull/1171))
## [3.8.2] - 2017-10-05
Released in 2017, still the most commonly used release.
[unreleased]: https://github.com/immutable-js/immutable-js/compare/v4.0.0-rc.15...HEAD
[4.0.0]: https://github.com/immutable-js/immutable-js/compare/v3.8.2...v4.0.0-rc.15
[3.8.2]: https://github.com/immutable-js/immutable-js/compare/3.7.6...v3.8.2