@coaction/history 1.1.0 → 1.3.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.
package/dist/index.js CHANGED
@@ -25,24 +25,90 @@ __export(index_exports, {
25
25
  module.exports = __toCommonJS(index_exports);
26
26
 
27
27
  // src/index.ts
28
- var toSnapshot = (state) => {
28
+ var toSnapshot = (state, visited = /* @__PURE__ */ new WeakMap()) => {
29
29
  if (Array.isArray(state)) {
30
- return state.map((item) => toSnapshot(item));
30
+ if (visited.has(state)) {
31
+ return visited.get(state);
32
+ }
33
+ const next = [];
34
+ visited.set(state, next);
35
+ for (const item of state) {
36
+ next.push(toSnapshot(item, visited));
37
+ }
38
+ return next;
31
39
  }
32
40
  if (typeof state === "object" && state !== null) {
41
+ if (visited.has(state)) {
42
+ return visited.get(state);
43
+ }
33
44
  const next = {};
34
- for (const key in state) {
45
+ visited.set(state, next);
46
+ for (const key of Object.keys(state)) {
35
47
  const value = state[key];
36
48
  if (typeof value === "function") {
37
49
  continue;
38
50
  }
39
- next[key] = toSnapshot(value);
51
+ next[key] = toSnapshot(value, visited);
40
52
  }
41
53
  return next;
42
54
  }
43
55
  return state;
44
56
  };
45
- var isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
57
+ var isEqual = (a, b, visited = /* @__PURE__ */ new WeakMap()) => {
58
+ if (Object.is(a, b)) {
59
+ return true;
60
+ }
61
+ if (Array.isArray(a) || Array.isArray(b)) {
62
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
63
+ return false;
64
+ }
65
+ for (let index = 0; index < a.length; index += 1) {
66
+ if (!isEqual(a[index], b[index], visited)) {
67
+ return false;
68
+ }
69
+ }
70
+ return true;
71
+ }
72
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
73
+ return false;
74
+ }
75
+ let seenTargets = visited.get(a);
76
+ if (!seenTargets) {
77
+ seenTargets = /* @__PURE__ */ new WeakSet();
78
+ visited.set(a, seenTargets);
79
+ } else if (seenTargets.has(b)) {
80
+ return true;
81
+ }
82
+ seenTargets.add(b);
83
+ const aObject = a;
84
+ const bObject = b;
85
+ const aKeys = Object.keys(aObject);
86
+ const bKeys = Object.keys(bObject);
87
+ if (aKeys.length !== bKeys.length) {
88
+ return false;
89
+ }
90
+ for (const key of aKeys) {
91
+ if (!Object.prototype.hasOwnProperty.call(bObject, key)) {
92
+ return false;
93
+ }
94
+ if (!isEqual(aObject[key], bObject[key], visited)) {
95
+ return false;
96
+ }
97
+ }
98
+ return true;
99
+ };
100
+ var applySnapshot = (target, nextState, currentState) => {
101
+ const next = nextState;
102
+ const current = currentState;
103
+ for (const key of Object.keys(current)) {
104
+ if (!Object.prototype.hasOwnProperty.call(next, key)) {
105
+ delete target[key];
106
+ }
107
+ }
108
+ for (const key of Object.keys(next)) {
109
+ target[key] = toSnapshot(next[key]);
110
+ }
111
+ };
46
112
  var history = ({
47
113
  limit = 100,
48
114
  partialize = (state) => state
@@ -81,7 +147,13 @@ var history = ({
81
147
  future.push(current);
82
148
  isTimeTraveling = true;
83
149
  try {
84
- baseSetState(previous);
150
+ baseSetState((draft) => {
151
+ applySnapshot(
152
+ draft,
153
+ previous,
154
+ current
155
+ );
156
+ });
85
157
  } finally {
86
158
  isTimeTraveling = false;
87
159
  }
@@ -96,7 +168,13 @@ var history = ({
96
168
  past.push(current);
97
169
  isTimeTraveling = true;
98
170
  try {
99
- baseSetState(next);
171
+ baseSetState((draft) => {
172
+ applySnapshot(
173
+ draft,
174
+ next,
175
+ current
176
+ );
177
+ });
100
178
  } finally {
101
179
  isTimeTraveling = false;
102
180
  }
package/dist/index.mjs CHANGED
@@ -1,22 +1,88 @@
1
1
  // src/index.ts
2
- var toSnapshot = (state) => {
2
+ var toSnapshot = (state, visited = /* @__PURE__ */ new WeakMap()) => {
3
3
  if (Array.isArray(state)) {
4
- return state.map((item) => toSnapshot(item));
4
+ if (visited.has(state)) {
5
+ return visited.get(state);
6
+ }
7
+ const next = [];
8
+ visited.set(state, next);
9
+ for (const item of state) {
10
+ next.push(toSnapshot(item, visited));
11
+ }
12
+ return next;
5
13
  }
6
14
  if (typeof state === "object" && state !== null) {
15
+ if (visited.has(state)) {
16
+ return visited.get(state);
17
+ }
7
18
  const next = {};
8
- for (const key in state) {
19
+ visited.set(state, next);
20
+ for (const key of Object.keys(state)) {
9
21
  const value = state[key];
10
22
  if (typeof value === "function") {
11
23
  continue;
12
24
  }
13
- next[key] = toSnapshot(value);
25
+ next[key] = toSnapshot(value, visited);
14
26
  }
15
27
  return next;
16
28
  }
17
29
  return state;
18
30
  };
19
- var isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
31
+ var isEqual = (a, b, visited = /* @__PURE__ */ new WeakMap()) => {
32
+ if (Object.is(a, b)) {
33
+ return true;
34
+ }
35
+ if (Array.isArray(a) || Array.isArray(b)) {
36
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
37
+ return false;
38
+ }
39
+ for (let index = 0; index < a.length; index += 1) {
40
+ if (!isEqual(a[index], b[index], visited)) {
41
+ return false;
42
+ }
43
+ }
44
+ return true;
45
+ }
46
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
47
+ return false;
48
+ }
49
+ let seenTargets = visited.get(a);
50
+ if (!seenTargets) {
51
+ seenTargets = /* @__PURE__ */ new WeakSet();
52
+ visited.set(a, seenTargets);
53
+ } else if (seenTargets.has(b)) {
54
+ return true;
55
+ }
56
+ seenTargets.add(b);
57
+ const aObject = a;
58
+ const bObject = b;
59
+ const aKeys = Object.keys(aObject);
60
+ const bKeys = Object.keys(bObject);
61
+ if (aKeys.length !== bKeys.length) {
62
+ return false;
63
+ }
64
+ for (const key of aKeys) {
65
+ if (!Object.prototype.hasOwnProperty.call(bObject, key)) {
66
+ return false;
67
+ }
68
+ if (!isEqual(aObject[key], bObject[key], visited)) {
69
+ return false;
70
+ }
71
+ }
72
+ return true;
73
+ };
74
+ var applySnapshot = (target, nextState, currentState) => {
75
+ const next = nextState;
76
+ const current = currentState;
77
+ for (const key of Object.keys(current)) {
78
+ if (!Object.prototype.hasOwnProperty.call(next, key)) {
79
+ delete target[key];
80
+ }
81
+ }
82
+ for (const key of Object.keys(next)) {
83
+ target[key] = toSnapshot(next[key]);
84
+ }
85
+ };
20
86
  var history = ({
21
87
  limit = 100,
22
88
  partialize = (state) => state
@@ -55,7 +121,13 @@ var history = ({
55
121
  future.push(current);
56
122
  isTimeTraveling = true;
57
123
  try {
58
- baseSetState(previous);
124
+ baseSetState((draft) => {
125
+ applySnapshot(
126
+ draft,
127
+ previous,
128
+ current
129
+ );
130
+ });
59
131
  } finally {
60
132
  isTimeTraveling = false;
61
133
  }
@@ -70,7 +142,13 @@ var history = ({
70
142
  past.push(current);
71
143
  isTimeTraveling = true;
72
144
  try {
73
- baseSetState(next);
145
+ baseSetState((draft) => {
146
+ applySnapshot(
147
+ draft,
148
+ next,
149
+ current
150
+ );
151
+ });
74
152
  } finally {
75
153
  isTimeTraveling = false;
76
154
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coaction/history",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "A undo/redo middleware for Coaction",
5
5
  "keywords": [
6
6
  "state",
@@ -40,7 +40,7 @@
40
40
  "url": "https://github.com/unadlib/coaction/issues"
41
41
  },
42
42
  "peerDependencies": {
43
- "coaction": "^1.1.0"
43
+ "coaction": "^1.3.0"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
46
  "coaction": {
@@ -48,7 +48,7 @@
48
48
  }
49
49
  },
50
50
  "devDependencies": {
51
- "coaction": "^1.1.0"
51
+ "coaction": "1.3.0"
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public",