Skip to content

Commit 2481809

Browse files
authored
while loop --> array methods (#117)
1 parent d420be5 commit 2481809

1 file changed

Lines changed: 35 additions & 31 deletions

File tree

src/temporal.ts

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,38 @@ export const temporalStateCreator = <TState>(
1515
futureStates: options?.futureStates || [],
1616
undo: (steps = 1) => {
1717
if (get().pastStates.length) {
18-
// Fastest way to clone an array on Chromium. Needed to create a new array reference
19-
const pastStates = get().pastStates.slice();
20-
const futureStates = get().futureStates.slice();
21-
// While loop is fastest in Chromium.
22-
// Based on the steps, get values from the pastStates array and push them to the futureStates array
23-
while (steps--) {
24-
const pastState = pastStates.pop();
25-
if (pastState) {
26-
futureStates.push(options?.partialize?.(userGet()) || userGet());
27-
userSet(pastState);
28-
}
29-
}
30-
set({ pastStates, futureStates });
18+
// userGet must be called before userSet
19+
const currentState = options?.partialize?.(userGet()) || userGet();
20+
21+
const statesToApply = get().pastStates.splice(-steps, steps);
22+
23+
// If there is length, we know that statesToApply is not empty
24+
userSet(statesToApply.shift()!);
25+
set({
26+
pastStates: get().pastStates,
27+
futureStates: get().futureStates.concat(
28+
currentState,
29+
statesToApply.reverse(),
30+
),
31+
});
3132
}
3233
},
3334
redo: (steps = 1) => {
3435
if (get().futureStates.length) {
35-
// Fastest way to clone an array on Chromium. Needed to create a new array reference
36-
const pastStates = get().pastStates.slice();
37-
const futureStates = get().futureStates.slice();
38-
// While loop is fastest in Chromium.
39-
// Based on the steps, get values from the futureStates array and push them to the pastStates array
40-
while (steps--) {
41-
const futureState = futureStates.pop();
42-
if (futureState) {
43-
pastStates.push(options?.partialize?.(userGet()) || userGet());
44-
userSet(futureState);
45-
}
46-
}
47-
set({ pastStates, futureStates });
36+
// userGet must be called before userSet
37+
const currentState = options?.partialize?.(userGet()) || userGet();
38+
39+
const statesToApply = get().futureStates.splice(-steps, steps);
40+
41+
// If there is length, we know that statesToApply is not empty
42+
userSet(statesToApply.shift()!);
43+
set({
44+
pastStates: get().pastStates.concat(
45+
currentState,
46+
statesToApply.reverse(),
47+
),
48+
futureStates: get().futureStates,
49+
});
4850
}
4951
},
5052
clear: () => set({ pastStates: [], futureStates: [] }),
@@ -58,14 +60,16 @@ export const temporalStateCreator = <TState>(
5860
if (get().isTracking) {
5961
const currentState = options?.partialize?.(userGet()) || userGet();
6062
if (!options?.equality?.(pastState, currentState)) {
61-
const pastStates = get().pastStates.slice();
6263
// This naively assumes that only one new state can be added at a time
63-
if (options?.limit && pastStates.length >= options?.limit) {
64-
pastStates.shift();
64+
if (options?.limit && get().pastStates.length >= options?.limit) {
65+
get().pastStates.shift();
6566
}
66-
pastStates.push(pastState);
67+
6768
get()._onSave?.(pastState, currentState);
68-
set({ pastStates, futureStates: [] });
69+
set({
70+
pastStates: get().pastStates.concat(pastState),
71+
futureStates: [],
72+
});
6973
}
7074
}
7175
},

0 commit comments

Comments
 (0)