Skip to content

Commit fc0d80c

Browse files
committed
Ensure getIn and updateIn are provided valid key path. Fixes immutable-js#256
1 parent 7cd0bc6 commit fc0d80c

File tree

7 files changed

+102
-63
lines changed

7 files changed

+102
-63
lines changed

__tests__/updateIn.ts

+21
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ describe('updateIn', () => {
1717
expect(m.getIn(I.fromJS(['a', 'b', 'c']))).toEqual(10);
1818
})
1919

20+
it('deep get throws without list or array-like', () => {
21+
// need to cast these as TypeScript first prevents us from such clownery.
22+
expect(() =>
23+
I.Map().getIn(<any>undefined)
24+
).toThrow('Expected iterable or array-like: undefined');
25+
expect(() =>
26+
I.Map().getIn(<any>{ a: 1, b: 2 })
27+
).toThrow('Expected iterable or array-like: [object Object]');
28+
})
29+
2030
it('deep get returns not found if path does not match', () => {
2131
var m = I.fromJS({a: {b: {c: 10}}});
2232
expect(m.getIn(['a', 'b', 'z'])).toEqual(undefined);
@@ -41,6 +51,17 @@ describe('updateIn', () => {
4151
);
4252
})
4353

54+
it('deep edit throws without list or array-like', () => {
55+
// need to cast these as TypeScript first prevents us from such clownery.
56+
expect(() =>
57+
I.Map().updateIn(<any>undefined, x => x)
58+
).toThrow('Expected iterable or array-like: undefined');
59+
expect(() =>
60+
I.Map().updateIn(<any>{ a: 1, b: 2 }, x => x)
61+
).toThrow('Expected iterable or array-like: [object Object]');
62+
})
63+
64+
4465
it('deep remove', () => {
4566
var m = I.fromJS({a: {b: {c: 10}}});
4667
expect(

dist/immutable.js

+21-13
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ function resolveEnd(end, size) {
109109
function resolveIndex(index, size, defaultIndex) {
110110
return index === undefined ? defaultIndex : index < 0 ? Math.max(0, size + index) : size === undefined ? index : Math.min(size, index);
111111
}
112+
function isArrayLike(value) {
113+
return value && typeof value.length === 'number';
114+
}
112115
var imul = typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 ? Math.imul : function imul(a, b) {
113116
a = a | 0;
114117
b = b | 0;
@@ -511,15 +514,13 @@ var $Iterable = Iterable;
511514
},
512515
getIn: function(searchKeyPath, notSetValue) {
513516
var nested = this;
514-
if (searchKeyPath) {
515-
var iter = getIterator(searchKeyPath) || getIterator($Iterable(searchKeyPath));
516-
var step;
517-
while (!(step = iter.next()).done) {
518-
var key = step.value;
519-
nested = nested && nested.get ? nested.get(key, NOT_SET) : NOT_SET;
520-
if (nested === NOT_SET) {
521-
return notSetValue;
522-
}
517+
var iter = forceIterator(searchKeyPath);
518+
var step;
519+
while (!(step = iter.next()).done) {
520+
var key = step.value;
521+
nested = nested && nested.get ? nested.get(key, NOT_SET) : NOT_SET;
522+
if (nested === NOT_SET) {
523+
return notSetValue;
523524
}
524525
}
525526
return nested;
@@ -822,6 +823,16 @@ function neg(predicate) {
822823
return -predicate.apply(this, arguments);
823824
};
824825
}
826+
function forceIterator(keyPath) {
827+
var iter = getIterator(keyPath);
828+
if (!iter) {
829+
if (!isArrayLike(keyPath)) {
830+
throw new TypeError('Expected iterable or array-like: ' + keyPath);
831+
}
832+
iter = getIterator(Iterable(keyPath));
833+
}
834+
return iter;
835+
}
825836
function quoteString(value) {
826837
return typeof value === 'string' ? JSON.stringify(value) : value;
827838
}
@@ -1167,9 +1178,6 @@ function seqFromValue(value) {
11671178
function maybeIndexedSeqFromValue(value) {
11681179
return (isArrayLike(value) ? new ArraySeq(value) : isIterator(value) ? new IteratorSeq(value) : hasIterator(value) ? new IterableSeq(value) : undefined);
11691180
}
1170-
function isArrayLike(value) {
1171-
return value && typeof value.length === 'number';
1172-
}
11731181
function seqIterate(seq, fn, reverse, useKeys) {
11741182
var cache = seq._cache;
11751183
if (cache) {
@@ -1289,7 +1297,7 @@ var Map = function Map(value) {
12891297
updater = notSetValue;
12901298
notSetValue = undefined;
12911299
}
1292-
var updatedValue = updateInDeepMap(this, getIterator(keyPath) || getIterator(Iterable(keyPath)), notSetValue, updater);
1300+
var updatedValue = updateInDeepMap(this, forceIterator(keyPath), notSetValue, updater);
12931301
return updatedValue === NOT_SET ? undefined : updatedValue;
12941302
},
12951303
clear: function() {

0 commit comments

Comments
 (0)