immutable 3.7.4 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,16 +9,21 @@ and change detection techniques with simple logic. [Persistent][] data presents
9
9
  a mutative API which does not update the data in-place, but instead always
10
10
  yields new updated data.
11
11
 
12
- `Immutable` provides Persistent Immutable `List`, `Stack`, `Map`, `OrderedMap`,
13
- `Set`, `OrderedSet` and `Record`. They are highly efficient on modern JavaScript
14
- VMs by using structural sharing via [hash maps tries][] and
15
- [vector tries][] as popularized by Clojure and Scala,
16
- minimizing the need to copy or cache data.
12
+ Immutable.js provides many Persistent Immutable data structures including:
13
+ `List`, `Stack`, `Map`, `OrderedMap`, `Set`, `OrderedSet` and `Record`.
14
+
15
+ These data structures are highly efficient on modern JavaScript VMs by using
16
+ structural sharing via [hash maps tries][] and [vector tries][] as popularized
17
+ by Clojure and Scala, minimizing the need to copy or cache data.
17
18
 
18
19
  `Immutable` also provides a lazy `Seq`, allowing efficient
19
20
  chaining of collection methods like `map` and `filter` without creating
20
21
  intermediate representations. Create some `Seq` with `Range` and `Repeat`.
21
22
 
23
+ Want to hear more? Watch the presentation about Immutable.js:
24
+
25
+ <a href="https://youtu.be/I7IdS-PbEgI" target="_blank" alt="Immutable Data and React"><img src="https://img.youtube.com/vi/I7IdS-PbEgI/0.jpg" /></a>
26
+
22
27
  [Persistent]: http://en.wikipedia.org/wiki/Persistent_data_structure
23
28
  [Immutable]: http://en.wikipedia.org/wiki/Immutable_object
24
29
  [hash maps tries]: http://en.wikipedia.org/wiki/Hash_array_mapped_trie
@@ -46,7 +51,7 @@ map2.get('b'); // 50
46
51
 
47
52
  ### Browser
48
53
 
49
- To use `immutable` from a browser, download [dist/immutable.min.js](./dist/immutable.min.js)
54
+ To use `immutable` from a browser, download [dist/immutable.min.js](https://github.com/facebook/immutable-js/blob/master/dist/immutable.min.js)
50
55
  or use a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
51
56
  or [jsDelivr](http://www.jsdelivr.com/#!immutable.js).
52
57
 
@@ -86,7 +91,7 @@ Just add a reference with a relative path to the type declarations at the top
86
91
  of your file.
87
92
 
88
93
  ```javascript
89
- ///<reference path='./node_modules/immutable/dist/Immutable.d.ts'/>
94
+ ///<reference path='./node_modules/immutable/dist/immutable.d.ts'/>
90
95
  import Immutable = require('immutable');
91
96
  var map1: Immutable.Map<string, number>;
92
97
  map1 = Immutable.Map({a:1, b:2, c:3});
@@ -103,8 +108,7 @@ Much of what makes application development difficult is tracking mutation and
103
108
  maintaining state. Developing with immutable data encourages you to think
104
109
  differently about how data flows through your application.
105
110
 
106
- Subscribing to data events throughout your application, by using
107
- `Object.observe`, or any other mechanism, creates a huge overhead of
111
+ Subscribing to data events throughout your application creates a huge overhead of
108
112
  book-keeping which can hurt performance, sometimes dramatically, and creates
109
113
  opportunities for areas of your application to get out of sync with each other
110
114
  due to easy to make programmer error. Since immutable data never changes,
@@ -222,6 +226,26 @@ Immutable.Seq(myObject).map(x => x * x).toObject();
222
226
  // { a: 1, b: 4, c: 9 }
223
227
  ```
224
228
 
229
+ Keep in mind, when using JS objects to construct Immutable Maps, that
230
+ JavaScript Object properties are always strings, even if written in a quote-less
231
+ shorthand, while Immutable Maps accept keys of any type.
232
+
233
+ ```js
234
+ var obj = { 1: "one" };
235
+ Object.keys(obj); // [ "1" ]
236
+ obj["1"]; // "one"
237
+ obj[1]; // "one"
238
+
239
+ var map = Immutable.fromJS(obj);
240
+ map.get("1"); // "one"
241
+ map.get(1); // undefined
242
+ ```
243
+
244
+ Property access for JavaScript Objects first converts the key to a string, but
245
+ since Immutable Map keys can be of any type the argument to `get()` is
246
+ not altered.
247
+
248
+
225
249
  ### Converts back to raw JavaScript objects.
226
250
 
227
251
  All `immutable` Iterables can be converted to plain JavaScript Arrays and
@@ -414,6 +438,12 @@ Also, don't miss the [Wiki](https://github.com/facebook/immutable-js/wiki) which
414
438
  contains articles on specific topics. Can't find something? Open an [issue](https://github.com/facebook/immutable-js/issues).
415
439
 
416
440
 
441
+ Testing
442
+ -------
443
+
444
+ If you are using the [Chai Assertion Library](http://chaijs.com/), [Chai Immutable](https://github.com/astorije/chai-immutable) provides a set of assertions to use against `Immutable` collections.
445
+
446
+
417
447
  Contribution
418
448
  ------------
419
449
 
@@ -435,7 +465,7 @@ Thanks
435
465
  and research in persistent data structures.
436
466
 
437
467
  [Hugh Jackson](https://github.com/hughfdjackson/), for providing the npm package
438
- name. If you're looking for his unsupported package, see [v1.4.1](https://www.npmjs.org/package/immutable/1.4.1).
468
+ name. If you're looking for his unsupported package, see [this repository](https://github.com/hughfdjackson/immutable).
439
469
 
440
470
 
441
471
  License
@@ -7,14 +7,21 @@ jest.autoMockOff();
7
7
  import Immutable = require('immutable');
8
8
  import Cursor = require('immutable/contrib/cursor');
9
9
 
10
- jasmine.getEnv().addEqualityTester((a, b) =>
11
- a instanceof Immutable.Iterable && b instanceof Immutable.Iterable ?
12
- Immutable.is(a, b) :
13
- jasmine.undefined
14
- );
15
-
16
10
  describe('Cursor', () => {
17
11
 
12
+ beforeEach(function () {
13
+ this.addMatchers({
14
+ toValueEqual: function (expected) {
15
+ var actual = this.actual;
16
+ if (!Immutable.is(expected, this.actual)) {
17
+ this.message = 'Expected\n' + this.actual + '\nto equal\n' + expected;
18
+ return false;
19
+ }
20
+ return true;
21
+ }
22
+ });
23
+ });
24
+
18
25
  var json = { a: { b: { c: 1 } } };
19
26
 
20
27
  it('gets from its path', () => {
@@ -60,7 +67,7 @@ describe('Cursor', () => {
60
67
  var data = Immutable.fromJS(json);
61
68
  var cursor = Cursor.from(data, ['a', 'b']);
62
69
  expect(cursor.toJS()).toEqual(json.a.b);
63
- expect(cursor).toEqual(data.getIn(['a', 'b']));
70
+ expect(cursor).toValueEqual(data.getIn(['a', 'b']));
64
71
  expect(cursor.size).toBe(1);
65
72
  expect(cursor.get('c')).toBe(1);
66
73
  });
@@ -85,19 +92,17 @@ describe('Cursor', () => {
85
92
  // cursor edits return new cursors:
86
93
  var newDeepCursor = deepCursor.update(x => x + 1);
87
94
  expect(newDeepCursor.deref()).toBe(2);
88
- expect(onChange).lastCalledWith(
89
- Immutable.fromJS({a:{b:{c:2}}}),
90
- data,
91
- ['a', 'b', 'c']
92
- );
95
+ var call1 = onChange.mock.calls[0];
96
+ expect(call1[0]).toValueEqual(Immutable.fromJS({a:{b:{c:2}}}));
97
+ expect(call1[1]).toBe(data);
98
+ expect(call1[2]).toEqual(['a', 'b', 'c']);
93
99
 
94
100
  var newestDeepCursor = newDeepCursor.update(x => x + 1);
95
101
  expect(newestDeepCursor.deref()).toBe(3);
96
- expect(onChange).lastCalledWith(
97
- Immutable.fromJS({a:{b:{c:3}}}),
98
- Immutable.fromJS({a:{b:{c:2}}}),
99
- ['a', 'b', 'c']
100
- );
102
+ var call2 = onChange.mock.calls[1];
103
+ expect(call2[0]).toValueEqual(Immutable.fromJS({a:{b:{c:3}}}));
104
+ expect(call2[1]).toValueEqual(Immutable.fromJS({a:{b:{c:2}}}));
105
+ expect(call2[2]).toEqual(['a', 'b', 'c']);
101
106
 
102
107
  // meanwhile, data is still immutable:
103
108
  expect(data.toJS()).toEqual(json);
@@ -106,11 +111,10 @@ describe('Cursor', () => {
106
111
  expect(deepCursor.deref()).toBe(1);
107
112
  var otherNewDeepCursor = deepCursor.update(x => x + 10);
108
113
  expect(otherNewDeepCursor.deref()).toBe(11);
109
- expect(onChange).lastCalledWith(
110
- Immutable.fromJS({a:{b:{c:11}}}),
111
- data,
112
- ['a', 'b', 'c']
113
- );
114
+ var call3 = onChange.mock.calls[2];
115
+ expect(call3[0]).toValueEqual(Immutable.fromJS({a:{b:{c:11}}}));
116
+ expect(call3[1]).toBe(data);
117
+ expect(call3[2]).toEqual(['a', 'b', 'c']);
114
118
 
115
119
  // and update has been called exactly thrice.
116
120
  expect(onChange.mock.calls.length).toBe(3);
@@ -126,21 +130,19 @@ describe('Cursor', () => {
126
130
  // onChange returning undefined has no effect
127
131
  var newCursor = deepCursor.update(x => x + 1);
128
132
  expect(newCursor.deref()).toBe(2);
129
- expect(onChange).lastCalledWith(
130
- Immutable.fromJS({a:{b:{c:2}}}),
131
- data,
132
- ['a', 'b', 'c']
133
- );
133
+ var call1 = onChange.mock.calls[0];
134
+ expect(call1[0]).toValueEqual(Immutable.fromJS({a:{b:{c:2}}}));
135
+ expect(call1[1]).toBe(data);
136
+ expect(call1[2]).toEqual(['a', 'b', 'c']);
134
137
 
135
138
  onChange.mockReturnValueOnce(Immutable.fromJS({a:{b:{c:11}}}));
136
139
  // onChange returning something else has an effect
137
140
  newCursor = newCursor.update(x => 999);
138
141
  expect(newCursor.deref()).toBe(11);
139
- expect(onChange).lastCalledWith(
140
- Immutable.fromJS({a:{b:{c:999}}}),
141
- Immutable.fromJS({a:{b:{c:2}}}),
142
- ['a', 'b', 'c']
143
- );
142
+ var call2 = onChange.mock.calls[1];
143
+ expect(call2[0]).toValueEqual(Immutable.fromJS({a:{b:{c:999}}}));
144
+ expect(call2[1]).toValueEqual(Immutable.fromJS({a:{b:{c:2}}}));
145
+ expect(call2[2]).toEqual(['a', 'b', 'c']);
144
146
 
145
147
  // and update has been called exactly twice
146
148
  expect(onChange.mock.calls.length).toBe(2);
@@ -154,14 +156,14 @@ describe('Cursor', () => {
154
156
  var bCursor = aCursor.cursor('b');
155
157
  var cCursor = bCursor.cursor('c');
156
158
 
157
- expect(bCursor.set('c', 10).deref()).toEqual(
159
+ expect(bCursor.set('c', 10).deref()).toValueEqual(
158
160
  Immutable.fromJS({ c: 10 })
159
161
  );
160
- expect(onChange).lastCalledWith(
161
- Immutable.fromJS({ a: { b: { c: 10 } } }),
162
- data,
163
- ['a', 'b', 'c']
164
- );
162
+
163
+ var call1 = onChange.mock.calls[0];
164
+ expect(call1[0]).toValueEqual(Immutable.fromJS({a:{b:{c:10}}}));
165
+ expect(call1[1]).toBe(data);
166
+ expect(call1[2]).toEqual(['a', 'b', 'c']);
165
167
  });
166
168
 
167
169
  it('creates maps as necessary', () => {
@@ -169,7 +171,7 @@ describe('Cursor', () => {
169
171
  var cursor = Cursor.from(data, ['a', 'b', 'c']);
170
172
  expect(cursor.deref()).toBe(undefined);
171
173
  cursor = cursor.set('d', 3);
172
- expect(cursor.deref()).toEqual(Immutable.Map({d: 3}));
174
+ expect(cursor.deref()).toValueEqual(Immutable.Map({d: 3}));
173
175
  });
174
176
 
175
177
  it('can set undefined', () => {
@@ -183,7 +185,7 @@ describe('Cursor', () => {
183
185
  it('has the sequence API', () => {
184
186
  var data = Immutable.Map({a: 1, b: 2, c: 3});
185
187
  var cursor = Cursor.from(data);
186
- expect(cursor.map((x: number) => x * x)).toEqual(Immutable.Map({a: 1, b: 4, c: 9}));
188
+ expect(cursor.map((x: number) => x * x)).toValueEqual(Immutable.Map({a: 1, b: 4, c: 9}));
187
189
  });
188
190
 
189
191
  it('can push values on a List', () => {
@@ -191,12 +193,12 @@ describe('Cursor', () => {
191
193
  var data = Immutable.fromJS({a: {b: [0, 1, 2]}});
192
194
  var cursor = Cursor.from(data, ['a', 'b'], onChange);
193
195
 
194
- expect(cursor.push(3,4)).toEqual(Immutable.List([0, 1, 2, 3, 4]));
195
- expect(onChange).lastCalledWith(
196
- Immutable.fromJS({a: {b: [0, 1, 2, 3, 4]}}),
197
- data,
198
- ['a', 'b']
199
- );
196
+ expect(cursor.push(3,4)).toValueEqual(Immutable.List([0, 1, 2, 3, 4]));
197
+
198
+ var call = onChange.mock.calls[0];
199
+ expect(call[0]).toValueEqual(Immutable.fromJS({a: {b: [0, 1, 2, 3, 4]}}));
200
+ expect(call[1]).toBe(data);
201
+ expect(call[2]).toEqual(['a', 'b']);
200
202
  });
201
203
 
202
204
  it('can pop values of a List', () => {
@@ -204,12 +206,12 @@ describe('Cursor', () => {
204
206
  var data = Immutable.fromJS({a: {b: [0, 1, 2]}});
205
207
  var cursor = Cursor.from(data, ['a', 'b'], onChange);
206
208
 
207
- expect(cursor.pop()).toEqual(Immutable.List([0, 1]));
208
- expect(onChange).lastCalledWith(
209
- Immutable.fromJS({a: {b: [0, 1]}}),
210
- data,
211
- ['a', 'b']
212
- );
209
+ expect(cursor.pop()).toValueEqual(Immutable.List([0, 1]));
210
+
211
+ var call = onChange.mock.calls[0];
212
+ expect(call[0]).toValueEqual(Immutable.fromJS({a: {b: [0, 1]}}));
213
+ expect(call[1]).toBe(data);
214
+ expect(call[2]).toEqual(['a', 'b']);
213
215
  });
214
216
 
215
217
  it('can unshift values on a List', () => {
@@ -217,12 +219,12 @@ describe('Cursor', () => {
217
219
  var data = Immutable.fromJS({a: {b: [0, 1, 2]}});
218
220
  var cursor = Cursor.from(data, ['a', 'b'], onChange);
219
221
 
220
- expect(cursor.unshift(-2, -1)).toEqual(Immutable.List([-2, -1, 0, 1, 2]));
221
- expect(onChange).lastCalledWith(
222
- Immutable.fromJS({a: {b: [-2, -1, 0, 1, 2]}}),
223
- data,
224
- ['a', 'b']
225
- );
222
+ expect(cursor.unshift(-2, -1)).toValueEqual(Immutable.List([-2, -1, 0, 1, 2]));
223
+
224
+ var call = onChange.mock.calls[0];
225
+ expect(call[0]).toValueEqual(Immutable.fromJS({a: {b: [-2, -1, 0, 1, 2]}}));
226
+ expect(call[1]).toBe(data);
227
+ expect(call[2]).toEqual(['a', 'b']);
226
228
  });
227
229
 
228
230
  it('can shift values of a List', () => {
@@ -230,12 +232,12 @@ describe('Cursor', () => {
230
232
  var data = Immutable.fromJS({a: {b: [0, 1, 2]}});
231
233
  var cursor = Cursor.from(data, ['a', 'b'], onChange);
232
234
 
233
- expect(cursor.shift()).toEqual(Immutable.List([1, 2]));
234
- expect(onChange).lastCalledWith(
235
- Immutable.fromJS({a: {b: [1, 2]}}),
236
- data,
237
- ['a', 'b']
238
- );
235
+ expect(cursor.shift()).toValueEqual(Immutable.List([1, 2]));
236
+
237
+ var call = onChange.mock.calls[0];
238
+ expect(call[0]).toValueEqual(Immutable.fromJS({a: {b: [1, 2]}}));
239
+ expect(call[1]).toBe(data);
240
+ expect(call[2]).toEqual(['a', 'b']);
239
241
  });
240
242
 
241
243
 
@@ -247,11 +249,11 @@ describe('Cursor', () => {
247
249
  var found = cursor.find(map => map.get('v') === 2);
248
250
  expect(typeof found.deref).toBe('function'); // is a cursor!
249
251
  found = found.set('v', 20);
250
- expect(onChange).lastCalledWith(
251
- Immutable.fromJS({a: {v: 1}, b: {v: 20}, c: {v: 3}}),
252
- data,
253
- ['b', 'v']
254
- );
252
+
253
+ var call = onChange.mock.calls[0];
254
+ expect(call[0]).toValueEqual(Immutable.fromJS({a: {v: 1}, b: {v: 20}, c: {v: 3}}));
255
+ expect(call[1]).toBe(data);
256
+ expect(call[2]).toEqual(['b', 'v']);
255
257
  });
256
258
 
257
259
  it('returns wrapped values for iteration API', () => {
@@ -309,7 +311,7 @@ describe('Cursor', () => {
309
311
  var c2 = c1.withMutations(m => m.set('x', 1).set('y', 2).set('z', 3));
310
312
 
311
313
  expect(c1.deref()).toEqual(undefined);
312
- expect(c2.deref()).toEqual(Immutable.fromJS(
314
+ expect(c2.deref()).toValueEqual(Immutable.fromJS(
313
315
  { x: 1, y: 2, z: 3 }
314
316
  ));
315
317
  expect(onChange.mock.calls.length).toBe(1);
@@ -334,11 +336,11 @@ describe('Cursor', () => {
334
336
  var c = Cursor.from(data, ['a'], onChange);
335
337
  var c1 = c.updateIn(['b', 'c'], x => x * 10);
336
338
  expect(c1.getIn(['b', 'c'])).toBe(10);
337
- expect(onChange).lastCalledWith(
338
- Immutable.fromJS({a:{b:{c:10}}}),
339
- data,
340
- ['a', 'b', 'c']
341
- );
339
+
340
+ var call = onChange.mock.calls[0];
341
+ expect(call[0]).toValueEqual(Immutable.fromJS({a:{b:{c:10}}}));
342
+ expect(call[1]).toBe(data);
343
+ expect(call[2]).toEqual(['a', 'b', 'c']);
342
344
  });
343
345
 
344
346
  it('can set deeply', () => {
@@ -347,11 +349,11 @@ describe('Cursor', () => {
347
349
  var c = Cursor.from(data, ['a'], onChange);
348
350
  var c1 = c.setIn(['b', 'c'], 10);
349
351
  expect(c1.getIn(['b', 'c'])).toBe(10);
350
- expect(onChange).lastCalledWith(
351
- Immutable.fromJS({a:{b:{c:10}}}),
352
- data,
353
- ['a', 'b', 'c']
354
- );
352
+
353
+ var call = onChange.mock.calls[0];
354
+ expect(call[0]).toValueEqual(Immutable.fromJS({a:{b:{c:10}}}));
355
+ expect(call[1]).toBe(data);
356
+ expect(call[2]).toEqual(['a', 'b', 'c']);
355
357
  });
356
358
 
357
359
  it('can get Record value as a property', () => {
@@ -362,4 +364,30 @@ describe('Cursor', () => {
362
364
  expect(cursor.first().name).toBe('John');
363
365
  });
364
366
 
367
+ it('can set value of a cursor directly', () => {
368
+ var onChange = jest.genMockFunction();
369
+ var data = Immutable.fromJS({a:1});
370
+ var c = Cursor.from(data, ['a'], onChange);
371
+ var c1 = c.set(2);
372
+ expect(c1.deref()).toBe(2);
373
+
374
+ var call = onChange.mock.calls[0];
375
+ expect(call[0]).toValueEqual(Immutable.fromJS({a:2}));
376
+ expect(call[1]).toBe(data);
377
+ expect(call[2]).toEqual(['a']);
378
+ });
379
+
380
+ it('can set value of a cursor to undefined directly', () => {
381
+ var onChange = jest.genMockFunction();
382
+ var data = Immutable.fromJS({a:1});
383
+ var c = Cursor.from(data, ['a'], onChange);
384
+ var c1 = c.set(undefined);
385
+ expect(c1.deref()).toBe(undefined);
386
+
387
+ var call = onChange.mock.calls[0];
388
+ expect(call[0]).toValueEqual(Immutable.fromJS({a:undefined}));
389
+ expect(call[1]).toBe(data);
390
+ expect(call[2]).toEqual(['a']);
391
+ });
392
+
365
393
  });
@@ -35,11 +35,9 @@
35
35
  * update the rest of your application.
36
36
  */
37
37
 
38
- declare module 'immutable/contrib/cursor' {
39
-
40
- ///<reference path='../../dist/immutable.d.ts'/>
41
- import Immutable = require('immutable');
38
+ /// <reference path='../../dist/immutable.d.ts'/>
42
39
 
40
+ declare module __Cursor {
43
41
 
44
42
  export function from(
45
43
  collection: Immutable.Collection<any, any>,
@@ -91,8 +89,11 @@ declare module 'immutable/contrib/cursor' {
91
89
  /**
92
90
  * Sets `value` at `key` in the cursor, returning a new cursor to the same
93
91
  * point in the new data.
92
+ *
93
+ * If only one parameter is provided, it is set directly as the cursor's value.
94
94
  */
95
95
  set(key: any, value: any): Cursor;
96
+ set(value: any): Cursor;
96
97
 
97
98
  /**
98
99
  * Deletes `key` from the cursor, returning a new cursor to the same
@@ -286,3 +287,7 @@ declare module 'immutable/contrib/cursor' {
286
287
  }
287
288
 
288
289
  }
290
+
291
+ declare module 'immutable/contrib/cursor' {
292
+ export = __Cursor
293
+ }
@@ -15,7 +15,7 @@
15
15
  * If you wish to use it in the browser, please check out Browserify or WebPack!
16
16
  */
17
17
 
18
- var Immutable = require('immutable');
18
+ var Immutable = require('../../');
19
19
  var Iterable = Immutable.Iterable;
20
20
  var Iterator = Iterable.Iterator;
21
21
  var Seq = Immutable.Seq;
@@ -86,7 +86,11 @@ IndexedCursorPrototype.getIn = function(keyPath, notSetValue) {
86
86
 
87
87
  IndexedCursorPrototype.set =
88
88
  KeyedCursorPrototype.set = function(key, value) {
89
- return updateCursor(this, function (m) { return m.set(key, value); }, [key]);
89
+ if(arguments.length === 1) {
90
+ return updateCursor(this, function() { return key; }, []);
91
+ } else {
92
+ return updateCursor(this, function (m) { return m.set(key, value); }, [key]);
93
+ }
90
94
  }
91
95
 
92
96
  IndexedCursorPrototype.push = function(/* values */) {