immutable 4.0.0-rc.6 → 4.0.0

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.
@@ -1,287 +0,0 @@
1
- /**
2
- * Copyright (c) 2014-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- /**
9
- * Cursors
10
- * -------
11
- *
12
- * Cursors allow you to hold a reference to a path in a nested immutable data
13
- * structure, allowing you to pass smaller sections of a larger nested
14
- * collection to portions of your application while maintaining a central point
15
- * aware of changes to the entire data structure.
16
- *
17
- * This is particularly useful when used in conjuction with component-based UI
18
- * libraries like [React](http://facebook.github.io/react/) or to simulate
19
- * "state" throughout an application while maintaining a single flow of logic.
20
- *
21
- * Cursors provide a simple API for getting the value at that path
22
- * (the equivalent of `this.getIn(keyPath)`), updating the value at that path
23
- * (the equivalent of `this.updateIn(keyPath)`), and getting a sub-cursor
24
- * starting from that path.
25
- *
26
- * When updated, a new root collection is created and provided to the `onChange`
27
- * function provided to the first call to `Cursor(map, onChange)`.
28
- *
29
- * When this cursor's (or any of its sub-cursors') `update` method is called,
30
- * the resulting new data structure will be provided to the `onChange`
31
- * function. Use this callback to keep track of the most current value or
32
- * update the rest of your application.
33
- */
34
-
35
- import * as Immutable from '../../';
36
-
37
- export function from(
38
- collection: Immutable.Collection<any, any>,
39
- onChange?: (newValue: any, oldValue?: any, keyPath?: Array<any>) => any
40
- ): Cursor;
41
- export function from(
42
- collection: Immutable.Collection<any, any>,
43
- keyPath: Array<any>,
44
- onChange?: (newValue: any, oldValue?: any, keyPath?: Array<any>) => any
45
- ): Cursor;
46
- export function from(
47
- collection: Immutable.Collection<any, any>,
48
- key: any,
49
- onChange?: (newValue: any, oldValue?: any, keyPath?: Array<any>) => any
50
- ): Cursor;
51
-
52
-
53
- export interface Cursor extends Immutable.Iterable<any, any>, Immutable.Seq<any, any> {
54
-
55
- /**
56
- * Returns a sub-cursor following the key-path starting from this cursor.
57
- */
58
- cursor(subKeyPath: Array<any>): Cursor;
59
- cursor(subKey: any): Cursor;
60
-
61
- /**
62
- * Returns the value at the cursor, if the cursor path does not yet exist,
63
- * returns `notSetValue`.
64
- */
65
- deref(notSetValue?: any): any;
66
-
67
- /**
68
- * Returns the value at the `key` in the cursor, or `notSetValue` if it
69
- * does not exist.
70
- *
71
- * If the key would return a collection, a new Cursor is returned.
72
- */
73
- get(key: any, notSetValue?: any): any;
74
-
75
- /**
76
- * Returns the value at the `keyPath` in the cursor, or `notSetValue` if it
77
- * does not exist.
78
- *
79
- * If the keyPath would return a collection, a new Cursor is returned.
80
- */
81
- getIn(keyPath: Array<any>, notSetValue?: any): any;
82
- getIn(keyPath: Immutable.Iterable<any, any>, notSetValue?: any): any;
83
-
84
- /**
85
- * Sets `value` at `key` in the cursor, returning a new cursor to the same
86
- * point in the new data.
87
- *
88
- * If only one parameter is provided, it is set directly as the cursor's value.
89
- */
90
- set(key: any, value: any): Cursor;
91
- set(value: any): Cursor;
92
-
93
- /**
94
- * Deletes `key` from the cursor, returning a new cursor to the same
95
- * point in the new data.
96
- *
97
- * Note: `delete` cannot be safely used in IE8
98
- * @alias remove
99
- */
100
- delete(key: any): Cursor;
101
- remove(key: any): Cursor;
102
-
103
- /**
104
- * Clears the value at this cursor, returning a new cursor to the same
105
- * point in the new data.
106
- */
107
- clear(): Cursor;
108
-
109
- /**
110
- * Updates the value in the data this cursor points to, triggering the
111
- * callback for the root cursor and returning a new cursor pointing to the
112
- * new data.
113
- */
114
- update(updater: (value: any) => any): Cursor;
115
- update(key: any, updater: (value: any) => any): Cursor;
116
- update(key: any, notSetValue: any, updater: (value: any) => any): Cursor;
117
-
118
- /**
119
- * @see `Map#merge`
120
- */
121
- merge(...iterables: Immutable.Iterable<any, any>[]): Cursor;
122
- merge(...iterables: {[key: string]: any}[]): Cursor;
123
-
124
- /**
125
- * @see `Map#mergeWith`
126
- */
127
- mergeWith(
128
- merger: (previous?: any, next?: any) => any,
129
- ...iterables: Immutable.Iterable<any, any>[]
130
- ): Cursor;
131
- mergeWith(
132
- merger: (previous?: any, next?: any) => any,
133
- ...iterables: {[key: string]: any}[]
134
- ): Cursor;
135
-
136
- /**
137
- * @see `Map#mergeDeep`
138
- */
139
- mergeDeep(...iterables: Immutable.Iterable<any, any>[]): Cursor;
140
- mergeDeep(...iterables: {[key: string]: any}[]): Cursor;
141
-
142
- /**
143
- * @see `Map#mergeDeepWith`
144
- */
145
- mergeDeepWith(
146
- merger: (previous?: any, next?: any) => any,
147
- ...iterables: Immutable.Iterable<any, any>[]
148
- ): Cursor;
149
- mergeDeepWith(
150
- merger: (previous?: any, next?: any) => any,
151
- ...iterables: {[key: string]: any}[]
152
- ): Cursor;
153
-
154
- // Deep persistent changes
155
-
156
- /**
157
- * Returns a new Cursor having set `value` at this `keyPath`. If any keys in
158
- * `keyPath` do not exist, a new immutable Map will be created at that key.
159
- */
160
- setIn(keyPath: Array<any>, value: any): Cursor;
161
- setIn(keyPath: Immutable.Iterable<any, any>, value: any): Cursor;
162
-
163
- /**
164
- * Returns a new Cursor with provided `values` appended
165
- */
166
- push(...values: Array<any>): Cursor;
167
-
168
- /**
169
- * Returns a new Cursor with a size ones less than this Cursor,
170
- * excluding the last index in this Cursor.
171
- */
172
- pop(): Cursor;
173
-
174
- /**
175
- * Returns a new Cursor with the provided `values` prepended,
176
- * shifting other values ahead to higher indices.
177
- */
178
- unshift(...values: Array<any>): Cursor;
179
-
180
- /**
181
- * Returns a new Cursor with a size ones less than this Cursor, excluding
182
- * the first index in this Cursor, shifting all other values to a lower index.
183
- */
184
- shift(): Cursor;
185
-
186
- /**
187
- * Returns a new Cursor having removed the value at this `keyPath`.
188
- *
189
- * @alias removeIn
190
- */
191
- deleteIn(keyPath: Array<any>): Cursor;
192
- deleteIn(keyPath: Immutable.Iterable<any, any>): Cursor;
193
- removeIn(keyPath: Array<any>): Cursor;
194
- removeIn(keyPath: Immutable.Iterable<any, any>): Cursor;
195
-
196
- /**
197
- * Returns a new Cursor having applied the `updater` to the value found at
198
- * the keyPath.
199
- *
200
- * If any keys in `keyPath` do not exist, new Immutable `Map`s will
201
- * be created at those keys. If the `keyPath` does not already contain a
202
- * value, the `updater` function will be called with `notSetValue`, if
203
- * provided, otherwise `undefined`.
204
- *
205
- * If the `updater` function returns the same value it was called with, then
206
- * no change will occur. This is still true if `notSetValue` is provided.
207
- */
208
- updateIn(
209
- keyPath: Array<any>,
210
- updater: (value: any) => any
211
- ): Cursor;
212
- updateIn(
213
- keyPath: Array<any>,
214
- notSetValue: any,
215
- updater: (value: any) => any
216
- ): Cursor;
217
- updateIn(
218
- keyPath: Immutable.Iterable<any, any>,
219
- updater: (value: any) => any
220
- ): Cursor;
221
- updateIn(
222
- keyPath: Immutable.Iterable<any, any>,
223
- notSetValue: any,
224
- updater: (value: any) => any
225
- ): Cursor;
226
-
227
- /**
228
- * A combination of `updateIn` and `merge`, returning a new Cursor, but
229
- * performing the merge at a point arrived at by following the keyPath.
230
- * In other words, these two lines are equivalent:
231
- *
232
- * x.updateIn(['a', 'b', 'c'], abc => abc.merge(y));
233
- * x.mergeIn(['a', 'b', 'c'], y);
234
- *
235
- */
236
- mergeIn(
237
- keyPath: Immutable.Iterable<any, any>,
238
- ...iterables: Immutable.Iterable<any, any>[]
239
- ): Cursor;
240
- mergeIn(
241
- keyPath: Array<any>,
242
- ...iterables: Immutable.Iterable<any, any>[]
243
- ): Cursor;
244
- mergeIn(
245
- keyPath: Array<any>,
246
- ...iterables: {[key: string]: any}[]
247
- ): Cursor;
248
-
249
- /**
250
- * A combination of `updateIn` and `mergeDeep`, returning a new Cursor, but
251
- * performing the deep merge at a point arrived at by following the keyPath.
252
- * In other words, these two lines are equivalent:
253
- *
254
- * x.updateIn(['a', 'b', 'c'], abc => abc.mergeDeep(y));
255
- * x.mergeDeepIn(['a', 'b', 'c'], y);
256
- *
257
- */
258
- mergeDeepIn(
259
- keyPath: Immutable.Iterable<any, any>,
260
- ...iterables: Immutable.Iterable<any, any>[]
261
- ): Cursor;
262
- mergeDeepIn(
263
- keyPath: Array<any>,
264
- ...iterables: Immutable.Iterable<any, any>[]
265
- ): Cursor;
266
- mergeDeepIn(
267
- keyPath: Array<any>,
268
- ...iterables: {[key: string]: any}[]
269
- ): Cursor;
270
-
271
- // Transient changes
272
-
273
- /**
274
- * Every time you call one of the above functions, a new immutable value is
275
- * created and the callback is triggered. If you need to apply a series of
276
- * mutations to a Cursor without triggering the callback repeatedly,
277
- * `withMutations()` creates a temporary mutable copy of the value which
278
- * can apply mutations in a highly performant manner. Afterwards the
279
- * callback is triggered with the final value.
280
- */
281
- withMutations(mutator: (mutable: any) => any): Cursor;
282
-
283
- /**
284
- * @ignore
285
- */
286
- map(fn: (v: any, k: any, c: this) => any): this;
287
- }
@@ -1,360 +0,0 @@
1
- /**
2
- * Copyright (c) 2014-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- /**
9
- * DEPRECATED
10
- *
11
- * The Cursor API is deprecated and will be removed in a future major release.
12
- *
13
- * It is strongly suggested that you use the excellent `immutable-cursor` module
14
- * which has an extremely similar API but is much higher quality.
15
- *
16
- * https://github.com/redbadger/immutable-cursor
17
- */
18
- typeof console === 'object' && console.warn && console.warn(
19
- 'The Cursor API is deprecated and will be removed in a future major release.\n' +
20
- '\n' +
21
- 'It is strongly suggested that you use the excellent `immutable-cursor` module\n' +
22
- 'which has an extremely similar API but is much higher quality.\n' +
23
- '\n' +
24
- 'https://github.com/redbadger/immutable-cursor\n' +
25
- );
26
-
27
- /**
28
- * Cursor is expected to be required in a node or other CommonJS context:
29
- *
30
- * var Cursor = require('immutable/contrib/cursor');
31
- *
32
- * If you wish to use it in the browser, please check out Browserify or WebPack!
33
- */
34
-
35
- var Immutable = require('../../');
36
- var Iterable = Immutable.Iterable;
37
- var Iterator = Iterable.Iterator;
38
- var Seq = Immutable.Seq;
39
- var Map = Immutable.Map;
40
- var Record = Immutable.Record;
41
-
42
-
43
- function cursorFrom(rootData, keyPath, onChange) {
44
- if (arguments.length === 1) {
45
- keyPath = [];
46
- } else if (typeof keyPath === 'function') {
47
- onChange = keyPath;
48
- keyPath = [];
49
- } else {
50
- keyPath = valToKeyPath(keyPath);
51
- }
52
- return makeCursor(rootData, keyPath, onChange);
53
- }
54
-
55
-
56
- var KeyedCursorPrototype = Object.create(Seq.Keyed.prototype);
57
- var IndexedCursorPrototype = Object.create(Seq.Indexed.prototype);
58
-
59
- function KeyedCursor(rootData, keyPath, onChange, size) {
60
- this.size = size;
61
- this._rootData = rootData;
62
- this._keyPath = keyPath;
63
- this._onChange = onChange;
64
- }
65
- KeyedCursorPrototype.constructor = KeyedCursor;
66
-
67
- function IndexedCursor(rootData, keyPath, onChange, size) {
68
- this.size = size;
69
- this._rootData = rootData;
70
- this._keyPath = keyPath;
71
- this._onChange = onChange;
72
- }
73
- IndexedCursorPrototype.constructor = IndexedCursor;
74
-
75
- KeyedCursorPrototype.toString = function() {
76
- return this.__toString('Cursor {', '}');
77
- }
78
- IndexedCursorPrototype.toString = function() {
79
- return this.__toString('Cursor [', ']');
80
- }
81
-
82
- KeyedCursorPrototype.deref =
83
- KeyedCursorPrototype.valueOf =
84
- IndexedCursorPrototype.deref =
85
- IndexedCursorPrototype.valueOf = function(notSetValue) {
86
- return this._rootData.getIn(this._keyPath, notSetValue);
87
- }
88
-
89
- KeyedCursorPrototype.get =
90
- IndexedCursorPrototype.get = function(key, notSetValue) {
91
- return this.getIn([key], notSetValue);
92
- }
93
-
94
- KeyedCursorPrototype.getIn =
95
- IndexedCursorPrototype.getIn = function(keyPath, notSetValue) {
96
- keyPath = listToKeyPath(keyPath);
97
- if (keyPath.length === 0) {
98
- return this;
99
- }
100
- var value = this._rootData.getIn(newKeyPath(this._keyPath, keyPath), NOT_SET);
101
- return value === NOT_SET ? notSetValue : wrappedValue(this, keyPath, value);
102
- }
103
-
104
- IndexedCursorPrototype.set =
105
- KeyedCursorPrototype.set = function(key, value) {
106
- if(arguments.length === 1) {
107
- return updateCursor(this, function() { return key; }, []);
108
- } else {
109
- return updateCursor(this, function (m) { return m.set(key, value); }, [key]);
110
- }
111
- }
112
-
113
- IndexedCursorPrototype.push = function(/* values */) {
114
- var args = arguments;
115
- return updateCursor(this, function (m) {
116
- return m.push.apply(m, args);
117
- });
118
- }
119
-
120
- IndexedCursorPrototype.pop = function() {
121
- return updateCursor(this, function (m) {
122
- return m.pop();
123
- });
124
- }
125
-
126
- IndexedCursorPrototype.unshift = function(/* values */) {
127
- var args = arguments;
128
- return updateCursor(this, function (m) {
129
- return m.unshift.apply(m, args);
130
- });
131
- }
132
-
133
- IndexedCursorPrototype.shift = function() {
134
- return updateCursor(this, function (m) {
135
- return m.shift();
136
- });
137
- }
138
-
139
- IndexedCursorPrototype.setIn =
140
- KeyedCursorPrototype.setIn = Map.prototype.setIn;
141
-
142
- KeyedCursorPrototype.remove =
143
- KeyedCursorPrototype['delete'] =
144
- IndexedCursorPrototype.remove =
145
- IndexedCursorPrototype['delete'] = function(key) {
146
- return updateCursor(this, function (m) { return m.remove(key); }, [key]);
147
- }
148
-
149
- IndexedCursorPrototype.removeIn =
150
- IndexedCursorPrototype.deleteIn =
151
- KeyedCursorPrototype.removeIn =
152
- KeyedCursorPrototype.deleteIn = Map.prototype.deleteIn;
153
-
154
- KeyedCursorPrototype.clear =
155
- IndexedCursorPrototype.clear = function() {
156
- return updateCursor(this, function (m) { return m.clear(); });
157
- }
158
-
159
- IndexedCursorPrototype.update =
160
- KeyedCursorPrototype.update = function(keyOrFn, notSetValue, updater) {
161
- return arguments.length === 1 ?
162
- updateCursor(this, keyOrFn) :
163
- this.updateIn([keyOrFn], notSetValue, updater);
164
- }
165
-
166
- IndexedCursorPrototype.updateIn =
167
- KeyedCursorPrototype.updateIn = function(keyPath, notSetValue, updater) {
168
- return updateCursor(this, function (m) {
169
- return m.updateIn(keyPath, notSetValue, updater);
170
- }, keyPath);
171
- }
172
-
173
- IndexedCursorPrototype.merge =
174
- KeyedCursorPrototype.merge = function(/*...iters*/) {
175
- var args = arguments;
176
- return updateCursor(this, function (m) {
177
- return m.merge.apply(m, args);
178
- });
179
- }
180
-
181
- IndexedCursorPrototype.mergeWith =
182
- KeyedCursorPrototype.mergeWith = function(merger/*, ...iters*/) {
183
- var args = arguments;
184
- return updateCursor(this, function (m) {
185
- return m.mergeWith.apply(m, args);
186
- });
187
- }
188
-
189
- IndexedCursorPrototype.mergeIn =
190
- KeyedCursorPrototype.mergeIn = Map.prototype.mergeIn;
191
-
192
- IndexedCursorPrototype.mergeDeep =
193
- KeyedCursorPrototype.mergeDeep = function(/*...iters*/) {
194
- var args = arguments;
195
- return updateCursor(this, function (m) {
196
- return m.mergeDeep.apply(m, args);
197
- });
198
- }
199
-
200
- IndexedCursorPrototype.mergeDeepWith =
201
- KeyedCursorPrototype.mergeDeepWith = function(merger/*, ...iters*/) {
202
- var args = arguments;
203
- return updateCursor(this, function (m) {
204
- return m.mergeDeepWith.apply(m, args);
205
- });
206
- }
207
-
208
- IndexedCursorPrototype.mergeDeepIn =
209
- KeyedCursorPrototype.mergeDeepIn = Map.prototype.mergeDeepIn;
210
-
211
- KeyedCursorPrototype.withMutations =
212
- IndexedCursorPrototype.withMutations = function(fn) {
213
- return updateCursor(this, function (m) {
214
- return (m || Map()).withMutations(fn);
215
- });
216
- }
217
-
218
- KeyedCursorPrototype.cursor =
219
- IndexedCursorPrototype.cursor = function(subKeyPath) {
220
- subKeyPath = valToKeyPath(subKeyPath);
221
- return subKeyPath.length === 0 ? this : subCursor(this, subKeyPath);
222
- }
223
-
224
- /**
225
- * All iterables need to implement __iterate
226
- */
227
- KeyedCursorPrototype.__iterate =
228
- IndexedCursorPrototype.__iterate = function(fn, reverse) {
229
- var cursor = this;
230
- var deref = cursor.deref();
231
- return deref && deref.__iterate ? deref.__iterate(
232
- function (v, k) { return fn(wrappedValue(cursor, [k], v), k, cursor); },
233
- reverse
234
- ) : 0;
235
- }
236
-
237
- /**
238
- * All iterables need to implement __iterator
239
- */
240
- KeyedCursorPrototype.__iterator =
241
- IndexedCursorPrototype.__iterator = function(type, reverse) {
242
- var deref = this.deref();
243
- var cursor = this;
244
- var iterator = deref && deref.__iterator &&
245
- deref.__iterator(Iterator.ENTRIES, reverse);
246
- return new Iterator(function () {
247
- if (!iterator) {
248
- return { value: undefined, done: true };
249
- }
250
- var step = iterator.next();
251
- if (step.done) {
252
- return step;
253
- }
254
- var entry = step.value;
255
- var k = entry[0];
256
- var v = wrappedValue(cursor, [k], entry[1]);
257
- return {
258
- value: type === Iterator.KEYS ? k : type === Iterator.VALUES ? v : [k, v],
259
- done: false
260
- };
261
- });
262
- }
263
-
264
- KeyedCursor.prototype = KeyedCursorPrototype;
265
- IndexedCursor.prototype = IndexedCursorPrototype;
266
-
267
-
268
- var NOT_SET = {}; // Sentinel value
269
-
270
- function makeCursor(rootData, keyPath, onChange, value) {
271
- if (arguments.length < 4) {
272
- value = rootData.getIn(keyPath);
273
- }
274
- var size = value && value.size;
275
- var CursorClass = Iterable.isIndexed(value) ? IndexedCursor : KeyedCursor;
276
- var cursor = new CursorClass(rootData, keyPath, onChange, size);
277
-
278
- if (value instanceof Record) {
279
- defineRecordProperties(cursor, value);
280
- }
281
-
282
- return cursor;
283
- }
284
-
285
- function defineRecordProperties(cursor, value) {
286
- try {
287
- value._keys.forEach(setProp.bind(undefined, cursor));
288
- } catch (error) {
289
- // Object.defineProperty failed. Probably IE8.
290
- }
291
- }
292
-
293
- function setProp(prototype, name) {
294
- Object.defineProperty(prototype, name, {
295
- get: function() {
296
- return this.get(name);
297
- },
298
- set: function(value) {
299
- if (!this.__ownerID) {
300
- throw new Error('Cannot set on an immutable record.');
301
- }
302
- }
303
- });
304
- }
305
-
306
- function wrappedValue(cursor, keyPath, value) {
307
- return Iterable.isIterable(value) ? subCursor(cursor, keyPath, value) : value;
308
- }
309
-
310
- function subCursor(cursor, keyPath, value) {
311
- if (arguments.length < 3) {
312
- return makeCursor( // call without value
313
- cursor._rootData,
314
- newKeyPath(cursor._keyPath, keyPath),
315
- cursor._onChange
316
- );
317
- }
318
- return makeCursor(
319
- cursor._rootData,
320
- newKeyPath(cursor._keyPath, keyPath),
321
- cursor._onChange,
322
- value
323
- );
324
- }
325
-
326
- function updateCursor(cursor, changeFn, changeKeyPath) {
327
- var deepChange = arguments.length > 2;
328
- var newRootData = cursor._rootData.updateIn(
329
- cursor._keyPath,
330
- deepChange ? Map() : undefined,
331
- changeFn
332
- );
333
- var keyPath = cursor._keyPath || [];
334
- var result = cursor._onChange && cursor._onChange.call(
335
- undefined,
336
- newRootData,
337
- cursor._rootData,
338
- deepChange ? newKeyPath(keyPath, changeKeyPath) : keyPath
339
- );
340
- if (result !== undefined) {
341
- newRootData = result;
342
- }
343
- return makeCursor(newRootData, cursor._keyPath, cursor._onChange);
344
- }
345
-
346
- function newKeyPath(head, tail) {
347
- return head.concat(listToKeyPath(tail));
348
- }
349
-
350
- function listToKeyPath(list) {
351
- return Array.isArray(list) ? list : Immutable.Iterable(list).toArray();
352
- }
353
-
354
- function valToKeyPath(val) {
355
- return Array.isArray(val) ? val :
356
- Iterable.isIterable(val) ? val.toArray() :
357
- [val];
358
- }
359
-
360
- exports.from = cursorFrom;