Skip to content

Commit 7b7dba9

Browse files
authored
Allow intermediate null value in getIn path. (immutable-js#1368)
Fixes immutable-js#1361 Closes immutable-js#1362
1 parent 140c8f5 commit 7b7dba9

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

__tests__/getIn.ts

+29-18
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,34 @@ describe('getIn', () => {
3434
).toThrow('Invalid keyPath: expected Ordered Collection or Array: abc');
3535
});
3636

37-
it('deep get throws if non-readable path', () => {
37+
function withWarnings(fn) {
3838
const realWarn = console.warn;
3939
const warnings: Array<any> = [];
4040
console.warn = w => warnings.push(w);
41-
4241
try {
43-
const deep = Map({ key: { regular: "jsobj" }, list: List([ Map({num: 10}) ]) });
44-
deep.getIn(["key", "foo", "item"]);
45-
expect(warnings.length).toBe(1);
46-
expect(warnings[0]).toBe(
47-
'Invalid keyPath: Value at ["key"] does not have a .get() method: [object Object]' +
48-
'\nThis warning will throw in a future version',
49-
);
50-
51-
warnings.length = 0;
52-
deep.getIn(["list", 0, "num", "badKey"]);
53-
expect(warnings.length).toBe(1);
54-
expect(warnings[0]).toBe(
55-
'Invalid keyPath: Value at ["list",0,"num"] does not have a .get() method: 10' +
56-
'\nThis warning will throw in a future version',
57-
);
42+
fn(warnings);
5843
} finally {
5944
console.warn = realWarn;
6045
}
61-
});
46+
}
47+
48+
it('deep get throws if non-readable path', withWarnings(warnings => {
49+
const deep = Map({ key: { regular: "jsobj" }, list: List([ Map({num: 10}) ]) });
50+
deep.getIn(["key", "foo", "item"]);
51+
expect(warnings.length).toBe(1);
52+
expect(warnings[0]).toBe(
53+
'Invalid keyPath: Value at ["key"] does not have a .get() method: [object Object]' +
54+
'\nThis warning will throw in a future version',
55+
);
56+
57+
warnings.length = 0;
58+
deep.getIn(["list", 0, "num", "badKey"]);
59+
expect(warnings.length).toBe(1);
60+
expect(warnings[0]).toBe(
61+
'Invalid keyPath: Value at ["list",0,"num"] does not have a .get() method: 10' +
62+
'\nThis warning will throw in a future version',
63+
);
64+
}));
6265

6366
it('deep get returns not found if path does not match', () => {
6467
const m = fromJS({a: {b: {c: 10}}});
@@ -76,4 +79,12 @@ describe('getIn', () => {
7679
expect(m.getIn(['a', 'b', 'd'], 123)).toEqual(undefined);
7780
});
7881

82+
it('deep get returns not found if path encounters null or undefined', withWarnings(warnings => {
83+
const m = fromJS({a: {b: {c: null, d: undefined}}});
84+
expect(m.getIn(['a', 'b', 'c', 'x'])).toEqual(undefined);
85+
expect(m.getIn(['a', 'b', 'd', 'x'])).toEqual(undefined);
86+
expect(m.getIn(['a', 'b', 'c', 'x'], 123)).toEqual(123);
87+
expect(m.getIn(['a', 'b', 'd', 'x'], 123)).toEqual(123);
88+
expect(warnings.length).toBe(0);
89+
}));
7990
});

src/CollectionImpl.js

+4
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,10 @@ function getIn(value, notSetValue, searchKeyPath, reportBadKeyPath) {
848848
const keyPath = coerceKeyPath(searchKeyPath);
849849
let i = 0;
850850
while (i !== keyPath.length) {
851+
// Intermediate null/undefined value along path
852+
if (value == null) {
853+
return notSetValue;
854+
}
851855
if (!value || !value.get) {
852856
if (reportBadKeyPath) {
853857
warn(

0 commit comments

Comments
 (0)