Skip to content

Commit a602dcb

Browse files
committed
Fix performance regression with cursors.
Closes immutable-js#284
1 parent 3540e35 commit a602dcb

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

contrib/cursor/index.js

+33-24
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ function cursorFrom(rootData, keyPath, onChange) {
2828
} else if (typeof keyPath === 'function') {
2929
onChange = keyPath;
3030
keyPath = [];
31-
} else if (!Array.isArray(keyPath)) {
32-
keyPath = [keyPath];
31+
} else {
32+
keyPath = valToKeyPath(keyPath);
3333
}
3434
return makeCursor(rootData, keyPath, onChange);
3535
}
@@ -74,20 +74,18 @@ IndexedCursorPrototype.get = function(key, notSetValue) {
7474
}
7575

7676
KeyedCursorPrototype.getIn =
77-
IndexedCursorPrototype.getIn = function(key, notSetValue) {
78-
if (!Array.isArray(key)) {
79-
key = Immutable.Iterable(key).toArray();
80-
}
81-
if (key.length === 0) {
77+
IndexedCursorPrototype.getIn = function(keyPath, notSetValue) {
78+
keyPath = listToKeyPath(keyPath);
79+
if (keyPath.length === 0) {
8280
return this;
8381
}
84-
var value = this._rootData.getIn(newKeyPath(this._keyPath, key), NOT_SET);
85-
return value === NOT_SET ? notSetValue : wrappedValue(this, key, value);
82+
var value = this._rootData.getIn(newKeyPath(this._keyPath, keyPath), NOT_SET);
83+
return value === NOT_SET ? notSetValue : wrappedValue(this, keyPath, value);
8684
}
8785

8886
IndexedCursorPrototype.set =
8987
KeyedCursorPrototype.set = function(key, value) {
90-
return updateCursor(this, function (m) { return m.set(key, value); }, key);
88+
return updateCursor(this, function (m) { return m.set(key, value); }, [key]);
9189
}
9290

9391
IndexedCursorPrototype.setIn =
@@ -97,7 +95,7 @@ KeyedCursorPrototype.remove =
9795
KeyedCursorPrototype['delete'] =
9896
IndexedCursorPrototype.remove =
9997
IndexedCursorPrototype['delete'] = function(key) {
100-
return updateCursor(this, function (m) { return m.remove(key); }, key);
98+
return updateCursor(this, function (m) { return m.remove(key); }, [key]);
10199
}
102100

103101
IndexedCursorPrototype.removeIn =
@@ -170,9 +168,9 @@ IndexedCursorPrototype.withMutations = function(fn) {
170168
}
171169

172170
KeyedCursorPrototype.cursor =
173-
IndexedCursorPrototype.cursor = function(subKey) {
174-
return Array.isArray(subKey) && subKey.length === 0 ?
175-
this : subCursor(this, subKey);
171+
IndexedCursorPrototype.cursor = function(subKeyPath) {
172+
subKeyPath = valToKeyPath(subKeyPath);
173+
return subKeyPath.length === 0 ? this : subCursor(this, subKeyPath);
176174
}
177175

178176
/**
@@ -183,7 +181,7 @@ IndexedCursorPrototype.__iterate = function(fn, reverse) {
183181
var cursor = this;
184182
var deref = cursor.deref();
185183
return deref && deref.__iterate ? deref.__iterate(
186-
function (v, k) { return fn(wrappedValue(cursor, k, v), k, cursor); },
184+
function (v, k) { return fn(wrappedValue(cursor, [k], v), k, cursor); },
187185
reverse
188186
) : 0;
189187
}
@@ -207,7 +205,7 @@ IndexedCursorPrototype.__iterator = function(type, reverse) {
207205
}
208206
var entry = step.value;
209207
var k = entry[0];
210-
var v = wrappedValue(cursor, k, entry[1]);
208+
var v = wrappedValue(cursor, [k], entry[1]);
211209
return {
212210
value: type === Iterator.KEYS ? k : type === Iterator.VALUES ? v : [k, v],
213211
done: false
@@ -230,31 +228,32 @@ function makeCursor(rootData, keyPath, onChange, value) {
230228
return new CursorClass(rootData, keyPath, onChange, size);
231229
}
232230

233-
function wrappedValue(cursor, key, value) {
234-
return Iterable.isIterable(value) ? subCursor(cursor, key, value) : value;
231+
function wrappedValue(cursor, keyPath, value) {
232+
return Iterable.isIterable(value) ? subCursor(cursor, keyPath, value) : value;
235233
}
236234

237-
function subCursor(cursor, key, value) {
235+
function subCursor(cursor, keyPath, value) {
238236
return makeCursor(
239237
cursor._rootData,
240-
newKeyPath(cursor._keyPath, key),
238+
newKeyPath(cursor._keyPath, keyPath),
241239
cursor._onChange,
242240
value
243241
);
244242
}
245243

246-
function updateCursor(cursor, changeFn, changeKey) {
244+
function updateCursor(cursor, changeFn, changeKeyPath) {
245+
var deepChange = arguments.length > 2;
247246
var newRootData = cursor._rootData.updateIn(
248247
cursor._keyPath,
249-
changeKey ? Map() : undefined,
248+
deepChange ? Map() : undefined,
250249
changeFn
251250
);
252251
var keyPath = cursor._keyPath || [];
253252
var result = cursor._onChange && cursor._onChange.call(
254253
undefined,
255254
newRootData,
256255
cursor._rootData,
257-
arguments.length > 2 ? newKeyPath(keyPath, changeKey) : keyPath
256+
deepChange ? newKeyPath(keyPath, changeKeyPath) : keyPath
258257
);
259258
if (result !== undefined) {
260259
newRootData = result;
@@ -263,7 +262,17 @@ function updateCursor(cursor, changeFn, changeKey) {
263262
}
264263

265264
function newKeyPath(head, tail) {
266-
return Seq(head).concat(tail).toArray();
265+
return head.concat(listToKeyPath(tail));
266+
}
267+
268+
function listToKeyPath(list) {
269+
return Array.isArray(list) ? list : Immutable.Iterable(list).toArray();
270+
}
271+
272+
function valToKeyPath(val) {
273+
return Array.isArray(val) ? val :
274+
Iterable.isIterable(val) ? val.toArray() :
275+
[val];
267276
}
268277

269278
exports.from = cursorFrom;

0 commit comments

Comments
 (0)