@yiin/reactive-proxy-state 1.0.12 → 1.0.14
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/computed.d.ts +6 -0
- package/dist/constants.d.ts +8 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1474 -11
- package/dist/reactive.d.ts +14 -2
- package/dist/ref.d.ts +24 -7
- package/dist/state.d.ts +6 -0
- package/dist/types.d.ts +1 -1
- package/dist/watch-effect.d.ts +2 -1
- package/dist/wrap-array.d.ts +2 -2
- package/dist/wrap-map.d.ts +2 -2
- package/dist/wrap-set.d.ts +2 -2
- package/package.json +2 -2
- package/dist/computed.js +0 -58
- package/dist/reactive.js +0 -114
- package/dist/ref.js +0 -91
- package/dist/state.js +0 -211
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -220
- package/dist/watch-effect.js +0 -154
- package/dist/watch.js +0 -44
- package/dist/watchEffect.d.ts +0 -54
- package/dist/watchEffect.js +0 -154
- package/dist/wrap-array.js +0 -237
- package/dist/wrap-map.js +0 -252
- package/dist/wrap-set.js +0 -182
- package/dist/wrapArray.d.ts +0 -2
- package/dist/wrapArray.js +0 -227
- package/dist/wrapMap.d.ts +0 -2
- package/dist/wrapMap.js +0 -230
- package/dist/wrapSet.d.ts +0 -2
- package/dist/wrapSet.js +0 -167
package/dist/wrap-array.js
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import { deepEqual, getPathConcat, setPathConcat, wrapperCache } from './utils';
|
|
2
|
-
import { reactive } from './reactive';
|
|
3
|
-
import { wrapMap } from './wrap-map';
|
|
4
|
-
import { wrapSet } from './wrap-set';
|
|
5
|
-
import { track, trigger } from './watch-effect';
|
|
6
|
-
// avoid repeated typeof checks
|
|
7
|
-
function isObject(v) {
|
|
8
|
-
return v && typeof v === 'object';
|
|
9
|
-
}
|
|
10
|
-
export function wrapArray(arr, emit, path) {
|
|
11
|
-
// reuse existing proxy if available for performance
|
|
12
|
-
const cachedProxy = wrapperCache.get(arr);
|
|
13
|
-
if (cachedProxy)
|
|
14
|
-
return cachedProxy;
|
|
15
|
-
// cache for wrapped methods to avoid re-creating them on each call
|
|
16
|
-
const methodCache = {};
|
|
17
|
-
const proxy = new Proxy(arr, {
|
|
18
|
-
get(target, prop, receiver) {
|
|
19
|
-
track(target, prop);
|
|
20
|
-
if (methodCache[prop]) {
|
|
21
|
-
return methodCache[prop];
|
|
22
|
-
}
|
|
23
|
-
// handle specific array mutation methods that require custom logic and event emission
|
|
24
|
-
switch (prop) {
|
|
25
|
-
case 'push':
|
|
26
|
-
track(target, 'length');
|
|
27
|
-
methodCache[prop] = function (...items) {
|
|
28
|
-
const oldLength = target.length;
|
|
29
|
-
const result = target.push(...items);
|
|
30
|
-
const newLength = target.length;
|
|
31
|
-
if (items.length > 0) {
|
|
32
|
-
const event = {
|
|
33
|
-
action: 'array-push',
|
|
34
|
-
path: path,
|
|
35
|
-
key: oldLength, // start index was the old length
|
|
36
|
-
items: items
|
|
37
|
-
};
|
|
38
|
-
emit(event);
|
|
39
|
-
trigger(target, Symbol.iterator);
|
|
40
|
-
if (oldLength !== newLength) {
|
|
41
|
-
trigger(target, 'length');
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return result;
|
|
45
|
-
};
|
|
46
|
-
return methodCache[prop];
|
|
47
|
-
case 'pop':
|
|
48
|
-
track(target, 'length');
|
|
49
|
-
methodCache[prop] = function () {
|
|
50
|
-
if (target.length === 0)
|
|
51
|
-
return undefined;
|
|
52
|
-
const oldLength = target.length;
|
|
53
|
-
const poppedIndex = oldLength - 1;
|
|
54
|
-
const oldValue = target[poppedIndex];
|
|
55
|
-
const result = target.pop();
|
|
56
|
-
const newLength = target.length;
|
|
57
|
-
const event = {
|
|
58
|
-
action: 'array-pop',
|
|
59
|
-
path: path,
|
|
60
|
-
key: poppedIndex,
|
|
61
|
-
oldValue: oldValue
|
|
62
|
-
};
|
|
63
|
-
emit(event);
|
|
64
|
-
trigger(target, Symbol.iterator);
|
|
65
|
-
if (oldLength !== newLength) {
|
|
66
|
-
trigger(target, 'length');
|
|
67
|
-
}
|
|
68
|
-
return result;
|
|
69
|
-
};
|
|
70
|
-
return methodCache[prop];
|
|
71
|
-
case 'shift':
|
|
72
|
-
track(target, 'length');
|
|
73
|
-
methodCache[prop] = function () {
|
|
74
|
-
if (target.length === 0)
|
|
75
|
-
return undefined;
|
|
76
|
-
const oldLength = target.length;
|
|
77
|
-
const oldValue = target[0];
|
|
78
|
-
const result = target.shift();
|
|
79
|
-
const newLength = target.length;
|
|
80
|
-
const event = {
|
|
81
|
-
action: 'array-shift',
|
|
82
|
-
path: path,
|
|
83
|
-
key: 0,
|
|
84
|
-
oldValue: oldValue
|
|
85
|
-
};
|
|
86
|
-
emit(event);
|
|
87
|
-
trigger(target, Symbol.iterator);
|
|
88
|
-
if (oldLength !== newLength) {
|
|
89
|
-
trigger(target, 'length');
|
|
90
|
-
}
|
|
91
|
-
return result;
|
|
92
|
-
};
|
|
93
|
-
return methodCache[prop];
|
|
94
|
-
case 'unshift':
|
|
95
|
-
track(target, 'length');
|
|
96
|
-
methodCache[prop] = function (...items) {
|
|
97
|
-
const oldLength = target.length;
|
|
98
|
-
const result = target.unshift(...items);
|
|
99
|
-
const newLength = target.length;
|
|
100
|
-
if (items.length > 0) {
|
|
101
|
-
const event = {
|
|
102
|
-
action: 'array-unshift',
|
|
103
|
-
path: path,
|
|
104
|
-
key: 0,
|
|
105
|
-
items: items
|
|
106
|
-
};
|
|
107
|
-
emit(event);
|
|
108
|
-
trigger(target, Symbol.iterator);
|
|
109
|
-
if (oldLength !== newLength) {
|
|
110
|
-
trigger(target, 'length');
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return result;
|
|
114
|
-
};
|
|
115
|
-
return methodCache[prop];
|
|
116
|
-
case 'splice':
|
|
117
|
-
track(target, 'length');
|
|
118
|
-
methodCache[prop] = function (start, deleteCount, ...items) {
|
|
119
|
-
const oldLength = target.length;
|
|
120
|
-
const actualStart = start < 0 ? Math.max(target.length + start, 0) : Math.min(start, target.length);
|
|
121
|
-
const deleteCountNum = deleteCount === undefined ? target.length - actualStart : Number(deleteCount);
|
|
122
|
-
const actualDeleteCount = Math.min(deleteCountNum, target.length - actualStart);
|
|
123
|
-
const deletedItems = target.slice(actualStart, actualStart + actualDeleteCount);
|
|
124
|
-
const result = target.splice(start, deleteCountNum, ...items);
|
|
125
|
-
const newLength = target.length;
|
|
126
|
-
if (actualDeleteCount > 0 || items.length > 0) {
|
|
127
|
-
const event = {
|
|
128
|
-
action: 'array-splice',
|
|
129
|
-
path: path,
|
|
130
|
-
key: actualStart,
|
|
131
|
-
deleteCount: actualDeleteCount,
|
|
132
|
-
items: items.length > 0 ? items : undefined,
|
|
133
|
-
oldValues: deletedItems.length > 0 ? deletedItems : undefined
|
|
134
|
-
};
|
|
135
|
-
emit(event);
|
|
136
|
-
trigger(target, Symbol.iterator);
|
|
137
|
-
if (oldLength !== newLength) {
|
|
138
|
-
trigger(target, 'length');
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return result;
|
|
142
|
-
};
|
|
143
|
-
return methodCache[prop];
|
|
144
|
-
// handle methods that rely on iteration state
|
|
145
|
-
case Symbol.iterator:
|
|
146
|
-
case 'values':
|
|
147
|
-
case 'keys':
|
|
148
|
-
case 'entries':
|
|
149
|
-
case 'forEach':
|
|
150
|
-
case 'map':
|
|
151
|
-
case 'filter':
|
|
152
|
-
case 'reduce':
|
|
153
|
-
case 'reduceRight':
|
|
154
|
-
case 'find':
|
|
155
|
-
case 'findIndex':
|
|
156
|
-
case 'every':
|
|
157
|
-
case 'some':
|
|
158
|
-
case 'join':
|
|
159
|
-
track(target, Symbol.iterator);
|
|
160
|
-
// fall through to default behavior (usually binding)
|
|
161
|
-
break;
|
|
162
|
-
case 'length':
|
|
163
|
-
track(target, 'length');
|
|
164
|
-
return Reflect.get(target, prop, receiver);
|
|
165
|
-
}
|
|
166
|
-
const value = Reflect.get(target, prop, receiver);
|
|
167
|
-
// determine if the property access is numeric array index access
|
|
168
|
-
const isNumericIndex = typeof prop === 'number' || (typeof prop === 'string' && !isNaN(parseInt(prop, 10)));
|
|
169
|
-
if (isNumericIndex) {
|
|
170
|
-
track(target, String(prop));
|
|
171
|
-
if (!isObject(value))
|
|
172
|
-
return value;
|
|
173
|
-
// reuse existing proxy for nested object/array if available
|
|
174
|
-
const cachedValueProxy = wrapperCache.get(value);
|
|
175
|
-
if (cachedValueProxy)
|
|
176
|
-
return cachedValueProxy;
|
|
177
|
-
// calculate the nested path for the element, optimizing with caching
|
|
178
|
-
const propKey = String(prop);
|
|
179
|
-
const pathKey = path.length > 0 ? `${path.join('.')}.${propKey}` : propKey;
|
|
180
|
-
let newPath = getPathConcat(pathKey);
|
|
181
|
-
if (newPath === undefined) {
|
|
182
|
-
newPath = path.concat(propKey);
|
|
183
|
-
setPathConcat(pathKey, newPath);
|
|
184
|
-
}
|
|
185
|
-
// recursively wrap nested structures
|
|
186
|
-
if (Array.isArray(value))
|
|
187
|
-
return wrapArray(value, emit, newPath);
|
|
188
|
-
if (value instanceof Map)
|
|
189
|
-
return wrapMap(value, emit, newPath);
|
|
190
|
-
if (value instanceof Set)
|
|
191
|
-
return wrapSet(value, emit, newPath);
|
|
192
|
-
if (value instanceof Date)
|
|
193
|
-
return new Date(value.getTime()); // dates are not proxied, return a copy
|
|
194
|
-
return reactive(value, emit, newPath);
|
|
195
|
-
}
|
|
196
|
-
// ensure functions accessed directly are bound to the original target
|
|
197
|
-
if (typeof value === 'function') {
|
|
198
|
-
return value.bind(target);
|
|
199
|
-
}
|
|
200
|
-
return value;
|
|
201
|
-
},
|
|
202
|
-
set(target, prop, value, receiver) {
|
|
203
|
-
const oldValue = target[prop];
|
|
204
|
-
// avoid unnecessary triggers if value hasn't changed
|
|
205
|
-
if (oldValue === value)
|
|
206
|
-
return true;
|
|
207
|
-
if (isObject(oldValue) && isObject(value) && deepEqual(oldValue, value, new WeakMap()))
|
|
208
|
-
return true;
|
|
209
|
-
const descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
210
|
-
const result = Reflect.set(target, prop, value, receiver);
|
|
211
|
-
const isNumericIndex = typeof prop === 'number' || (typeof prop === 'string' && !isNaN(parseInt(String(prop))));
|
|
212
|
-
// emit event and trigger effects only if the set was successful and wasn't intercepted by a setter
|
|
213
|
-
// (unless it's a direct numeric index set, which doesn't have a descriptor.set)
|
|
214
|
-
if (result && (!descriptor || !descriptor.set || isNumericIndex)) {
|
|
215
|
-
const propKey = String(prop);
|
|
216
|
-
const pathKey = path.length > 0 ? `${path.join('.')}.${propKey}` : propKey;
|
|
217
|
-
let newPath = getPathConcat(pathKey);
|
|
218
|
-
if (newPath === undefined) {
|
|
219
|
-
newPath = path.concat(propKey);
|
|
220
|
-
setPathConcat(pathKey, newPath);
|
|
221
|
-
}
|
|
222
|
-
const event = {
|
|
223
|
-
action: 'set',
|
|
224
|
-
path: newPath,
|
|
225
|
-
oldValue,
|
|
226
|
-
newValue: value
|
|
227
|
-
};
|
|
228
|
-
emit(event);
|
|
229
|
-
trigger(target, prop);
|
|
230
|
-
}
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
// cache the newly created proxy before returning
|
|
235
|
-
wrapperCache.set(arr, proxy);
|
|
236
|
-
return proxy;
|
|
237
|
-
}
|
package/dist/wrap-map.js
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import { deepEqual, getPathConcat, setPathConcat, wrapperCache } from './utils';
|
|
2
|
-
import { reactive } from './reactive';
|
|
3
|
-
import { wrapArray } from './wrap-array';
|
|
4
|
-
import { wrapSet } from './wrap-set';
|
|
5
|
-
import { track, trigger } from './watch-effect';
|
|
6
|
-
export function wrapMap(map, emit, path) {
|
|
7
|
-
// reuse existing proxy if available for performance
|
|
8
|
-
const cachedProxy = wrapperCache.get(map);
|
|
9
|
-
if (cachedProxy)
|
|
10
|
-
return cachedProxy;
|
|
11
|
-
// cache for wrapped methods to avoid re-creating them on each call
|
|
12
|
-
const methodCache = {};
|
|
13
|
-
const proxy = new Proxy(map, {
|
|
14
|
-
get(target, prop, receiver) {
|
|
15
|
-
track(target, prop);
|
|
16
|
-
// iteration methods need to track the iterator symbol on every access
|
|
17
|
-
// to re-establish dependency after effect cleanup, even when cached
|
|
18
|
-
if (prop === Symbol.iterator || prop === 'entries' || prop === 'values' || prop === 'keys' || prop === 'forEach') {
|
|
19
|
-
track(target, Symbol.iterator);
|
|
20
|
-
}
|
|
21
|
-
if (methodCache[prop]) {
|
|
22
|
-
return methodCache[prop];
|
|
23
|
-
}
|
|
24
|
-
if (prop === 'set') {
|
|
25
|
-
methodCache[prop] = function (key, value) {
|
|
26
|
-
const existed = target.has(key);
|
|
27
|
-
const oldValue = target.get(key);
|
|
28
|
-
const oldSize = target.size;
|
|
29
|
-
// avoid unnecessary work if value hasn't changed
|
|
30
|
-
if (oldValue === value)
|
|
31
|
-
return receiver;
|
|
32
|
-
if (oldValue && typeof oldValue === 'object' && value && typeof value === 'object' && deepEqual(oldValue, value, new WeakMap()))
|
|
33
|
-
return receiver;
|
|
34
|
-
target.set(key, value);
|
|
35
|
-
const newSize = target.size;
|
|
36
|
-
// optimize path calculation by caching concatenated paths
|
|
37
|
-
const pathKey = path.join('.');
|
|
38
|
-
let cachedPath = getPathConcat(pathKey);
|
|
39
|
-
if (cachedPath === undefined) {
|
|
40
|
-
cachedPath = path;
|
|
41
|
-
setPathConcat(pathKey, cachedPath);
|
|
42
|
-
}
|
|
43
|
-
const event = {
|
|
44
|
-
action: 'map-set',
|
|
45
|
-
path: cachedPath,
|
|
46
|
-
key,
|
|
47
|
-
oldValue,
|
|
48
|
-
newValue: value
|
|
49
|
-
};
|
|
50
|
-
emit(event);
|
|
51
|
-
// trigger effects based on whether it was an add or update
|
|
52
|
-
if (!existed) {
|
|
53
|
-
trigger(target, Symbol.iterator);
|
|
54
|
-
if (oldSize !== newSize) {
|
|
55
|
-
trigger(target, 'size');
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
trigger(target, String(key));
|
|
60
|
-
}
|
|
61
|
-
return receiver;
|
|
62
|
-
};
|
|
63
|
-
return methodCache[prop];
|
|
64
|
-
}
|
|
65
|
-
if (prop === 'delete') {
|
|
66
|
-
methodCache[prop] = function (key) {
|
|
67
|
-
const existed = target.has(key);
|
|
68
|
-
if (!existed)
|
|
69
|
-
return false;
|
|
70
|
-
const oldValue = target.get(key);
|
|
71
|
-
const oldSize = target.size;
|
|
72
|
-
const result = target.delete(key);
|
|
73
|
-
const newSize = target.size;
|
|
74
|
-
if (result) { // only emit and trigger if delete was successful
|
|
75
|
-
const pathKey = path.join('.');
|
|
76
|
-
let cachedPath = getPathConcat(pathKey);
|
|
77
|
-
if (cachedPath === undefined) {
|
|
78
|
-
cachedPath = path;
|
|
79
|
-
setPathConcat(pathKey, cachedPath);
|
|
80
|
-
}
|
|
81
|
-
const event = {
|
|
82
|
-
action: 'map-delete',
|
|
83
|
-
path: cachedPath,
|
|
84
|
-
key,
|
|
85
|
-
oldValue
|
|
86
|
-
};
|
|
87
|
-
emit(event);
|
|
88
|
-
trigger(target, Symbol.iterator);
|
|
89
|
-
if (oldSize !== newSize) {
|
|
90
|
-
trigger(target, 'size');
|
|
91
|
-
}
|
|
92
|
-
trigger(target, String(key));
|
|
93
|
-
}
|
|
94
|
-
return result;
|
|
95
|
-
};
|
|
96
|
-
return methodCache[prop];
|
|
97
|
-
}
|
|
98
|
-
if (prop === 'clear') {
|
|
99
|
-
methodCache[prop] = function () {
|
|
100
|
-
const oldSize = target.size;
|
|
101
|
-
if (oldSize === 0)
|
|
102
|
-
return;
|
|
103
|
-
target.clear();
|
|
104
|
-
const newSize = target.size;
|
|
105
|
-
const event = {
|
|
106
|
-
action: 'map-clear',
|
|
107
|
-
path: path,
|
|
108
|
-
key: null
|
|
109
|
-
};
|
|
110
|
-
emit(event);
|
|
111
|
-
trigger(target, Symbol.iterator);
|
|
112
|
-
if (oldSize !== newSize) {
|
|
113
|
-
trigger(target, 'size');
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
return methodCache[prop];
|
|
117
|
-
}
|
|
118
|
-
if (prop === 'get') {
|
|
119
|
-
// return a function that tracks the specific key only when called
|
|
120
|
-
methodCache[prop] = function (key) {
|
|
121
|
-
track(target, String(key));
|
|
122
|
-
const value = target.get(key);
|
|
123
|
-
if (!value || typeof value !== 'object')
|
|
124
|
-
return value;
|
|
125
|
-
const cachedValueProxy = wrapperCache.get(value);
|
|
126
|
-
if (cachedValueProxy)
|
|
127
|
-
return cachedValueProxy;
|
|
128
|
-
const keyString = String(key);
|
|
129
|
-
const pathKey = path.length > 0 ? `${path.join('.')}.${keyString}` : keyString;
|
|
130
|
-
let newPath = getPathConcat(pathKey);
|
|
131
|
-
if (newPath === undefined) {
|
|
132
|
-
newPath = path.concat(keyString);
|
|
133
|
-
setPathConcat(pathKey, newPath);
|
|
134
|
-
}
|
|
135
|
-
// recursively wrap nested structures
|
|
136
|
-
if (value instanceof Map)
|
|
137
|
-
return wrapMap(value, emit, newPath);
|
|
138
|
-
if (value instanceof Set)
|
|
139
|
-
return wrapSet(value, emit, newPath);
|
|
140
|
-
if (Array.isArray(value))
|
|
141
|
-
return wrapArray(value, emit, newPath);
|
|
142
|
-
if (value instanceof Date)
|
|
143
|
-
return new Date(value.getTime()); // dates are not proxied, return a copy
|
|
144
|
-
return reactive(value, emit, newPath);
|
|
145
|
-
};
|
|
146
|
-
return methodCache[prop];
|
|
147
|
-
}
|
|
148
|
-
if (prop === 'has') {
|
|
149
|
-
track(target, Symbol.iterator);
|
|
150
|
-
methodCache[prop] = function (key) {
|
|
151
|
-
// track the specific key only when 'has' is called
|
|
152
|
-
track(target, String(key));
|
|
153
|
-
return target.has(key);
|
|
154
|
-
}.bind(target); // bind is still okay here, doesn't interfere with caching
|
|
155
|
-
return methodCache[prop];
|
|
156
|
-
}
|
|
157
|
-
// handle iteration methods
|
|
158
|
-
if (prop === Symbol.iterator || prop === 'entries' || prop === 'values' || prop === 'keys' || prop === 'forEach') {
|
|
159
|
-
track(target, Symbol.iterator);
|
|
160
|
-
const originalMethod = Reflect.get(target, prop, receiver);
|
|
161
|
-
// return custom iterators/foreach that wrap values during iteration
|
|
162
|
-
if (prop === 'forEach') {
|
|
163
|
-
methodCache[prop] = (callbackfn, thisArg) => {
|
|
164
|
-
// use the proxied .entries() to ensure values passed to callback are wrapped and tracked
|
|
165
|
-
const entriesIterator = proxy.entries();
|
|
166
|
-
for (const [key, value] of entriesIterator) {
|
|
167
|
-
callbackfn.call(thisArg, value, key, proxy);
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
return methodCache[prop];
|
|
171
|
-
}
|
|
172
|
-
// handle symbol.iterator, entries, values, keys by creating generator functions
|
|
173
|
-
methodCache[prop] = function* (...args) {
|
|
174
|
-
const iterator = originalMethod.apply(target, args);
|
|
175
|
-
for (const entry of iterator) {
|
|
176
|
-
let keyToWrap = entry;
|
|
177
|
-
let valueToWrap = entry;
|
|
178
|
-
let isEntry = false;
|
|
179
|
-
if (prop === 'entries' || prop === Symbol.iterator) {
|
|
180
|
-
keyToWrap = entry[0];
|
|
181
|
-
valueToWrap = entry[1];
|
|
182
|
-
isEntry = true;
|
|
183
|
-
}
|
|
184
|
-
// wrap key if it's an object
|
|
185
|
-
// note: reactivity on map keys can be complex/unexpected
|
|
186
|
-
let wrappedKey = keyToWrap;
|
|
187
|
-
if (isEntry && keyToWrap && typeof keyToWrap === 'object') {
|
|
188
|
-
const pathKey = path.length > 0 ? `${path.join('.')}.${String(keyToWrap)}` : String(keyToWrap);
|
|
189
|
-
let keyPath = getPathConcat(pathKey);
|
|
190
|
-
if (keyPath === undefined) {
|
|
191
|
-
keyPath = path.concat(String(keyToWrap));
|
|
192
|
-
setPathConcat(pathKey, keyPath);
|
|
193
|
-
}
|
|
194
|
-
// todo: decide if map keys should be deeply reactive
|
|
195
|
-
wrappedKey = reactive(keyToWrap, emit, keyPath);
|
|
196
|
-
}
|
|
197
|
-
// wrap value if it's an object
|
|
198
|
-
let wrappedValue = valueToWrap;
|
|
199
|
-
if (valueToWrap && typeof valueToWrap === 'object') {
|
|
200
|
-
const cachedValueProxy = wrapperCache.get(valueToWrap);
|
|
201
|
-
if (cachedValueProxy) {
|
|
202
|
-
wrappedValue = cachedValueProxy;
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
const keyString = String(keyToWrap); // use original key for path
|
|
206
|
-
const pathKey = path.length > 0 ? `${path.join('.')}.${keyString}` : keyString;
|
|
207
|
-
let newPath = getPathConcat(pathKey);
|
|
208
|
-
if (newPath === undefined) {
|
|
209
|
-
newPath = path.concat(keyString);
|
|
210
|
-
setPathConcat(pathKey, newPath);
|
|
211
|
-
}
|
|
212
|
-
if (valueToWrap instanceof Map)
|
|
213
|
-
wrappedValue = wrapMap(valueToWrap, emit, newPath);
|
|
214
|
-
else if (valueToWrap instanceof Set)
|
|
215
|
-
wrappedValue = wrapSet(valueToWrap, emit, newPath);
|
|
216
|
-
else if (Array.isArray(valueToWrap))
|
|
217
|
-
wrappedValue = wrapArray(valueToWrap, emit, newPath);
|
|
218
|
-
else if (valueToWrap instanceof Date)
|
|
219
|
-
wrappedValue = new Date(valueToWrap.getTime());
|
|
220
|
-
else
|
|
221
|
-
wrappedValue = reactive(valueToWrap, emit, newPath);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
if (prop === 'entries' || prop === Symbol.iterator) {
|
|
225
|
-
yield [wrappedKey, wrappedValue];
|
|
226
|
-
}
|
|
227
|
-
else if (prop === 'values') {
|
|
228
|
-
yield wrappedValue;
|
|
229
|
-
}
|
|
230
|
-
else { // keys
|
|
231
|
-
yield wrappedKey;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
return methodCache[prop];
|
|
236
|
-
}
|
|
237
|
-
if (prop === 'size') {
|
|
238
|
-
track(target, 'size');
|
|
239
|
-
return target.size;
|
|
240
|
-
}
|
|
241
|
-
const value = Reflect.get(target, prop, receiver);
|
|
242
|
-
// Bind plain functions accessed directly (e.g., toString)
|
|
243
|
-
if (typeof value === 'function') {
|
|
244
|
-
return value.bind(target);
|
|
245
|
-
}
|
|
246
|
-
return value;
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
// cache the newly created proxy before returning
|
|
250
|
-
wrapperCache.set(map, proxy);
|
|
251
|
-
return proxy;
|
|
252
|
-
}
|
package/dist/wrap-set.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { getPathConcat, setPathConcat, wrapperCache } from './utils';
|
|
2
|
-
import { reactive } from './reactive';
|
|
3
|
-
import { wrapArray } from './wrap-array';
|
|
4
|
-
import { wrapMap } from './wrap-map';
|
|
5
|
-
import { track, trigger } from './watch-effect';
|
|
6
|
-
export function wrapSet(set, emit, path) {
|
|
7
|
-
// reuse existing proxy if available for performance
|
|
8
|
-
const cachedProxy = wrapperCache.get(set);
|
|
9
|
-
if (cachedProxy)
|
|
10
|
-
return cachedProxy;
|
|
11
|
-
// cache for wrapped methods to avoid re-creating them on each call
|
|
12
|
-
const methodCache = {};
|
|
13
|
-
const proxy = new Proxy(set, {
|
|
14
|
-
get(target, prop, receiver) {
|
|
15
|
-
track(target, prop);
|
|
16
|
-
if (methodCache[prop]) {
|
|
17
|
-
return methodCache[prop];
|
|
18
|
-
}
|
|
19
|
-
if (prop === 'add') {
|
|
20
|
-
methodCache[prop] = function (value) {
|
|
21
|
-
const existed = target.has(value);
|
|
22
|
-
const oldSize = target.size;
|
|
23
|
-
// only add and trigger if the value doesn't already exist
|
|
24
|
-
if (!existed) {
|
|
25
|
-
target.add(value);
|
|
26
|
-
const newSize = target.size;
|
|
27
|
-
const event = {
|
|
28
|
-
action: 'set-add',
|
|
29
|
-
path: path,
|
|
30
|
-
value: value
|
|
31
|
-
};
|
|
32
|
-
emit(event);
|
|
33
|
-
trigger(target, Symbol.iterator);
|
|
34
|
-
if (oldSize !== newSize) {
|
|
35
|
-
trigger(target, 'size');
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return receiver; // return the proxy itself for chaining
|
|
39
|
-
};
|
|
40
|
-
return methodCache[prop];
|
|
41
|
-
}
|
|
42
|
-
if (prop === 'delete') {
|
|
43
|
-
methodCache[prop] = function (value) {
|
|
44
|
-
const existed = target.has(value);
|
|
45
|
-
const oldSize = target.size;
|
|
46
|
-
if (existed) {
|
|
47
|
-
const oldValue = value;
|
|
48
|
-
const result = target.delete(value);
|
|
49
|
-
const newSize = target.size;
|
|
50
|
-
if (result) { // only emit and trigger if delete was successful
|
|
51
|
-
const event = {
|
|
52
|
-
action: 'set-delete',
|
|
53
|
-
path: path,
|
|
54
|
-
value: value,
|
|
55
|
-
oldValue: oldValue
|
|
56
|
-
};
|
|
57
|
-
emit(event);
|
|
58
|
-
trigger(target, Symbol.iterator);
|
|
59
|
-
if (oldSize !== newSize) {
|
|
60
|
-
trigger(target, 'size');
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return result;
|
|
64
|
-
}
|
|
65
|
-
return false;
|
|
66
|
-
};
|
|
67
|
-
return methodCache[prop];
|
|
68
|
-
}
|
|
69
|
-
if (prop === 'clear') {
|
|
70
|
-
methodCache[prop] = function () {
|
|
71
|
-
const oldSize = target.size;
|
|
72
|
-
if (oldSize === 0)
|
|
73
|
-
return;
|
|
74
|
-
target.clear();
|
|
75
|
-
const newSize = target.size;
|
|
76
|
-
const event = {
|
|
77
|
-
action: 'set-clear',
|
|
78
|
-
path: path,
|
|
79
|
-
value: null
|
|
80
|
-
};
|
|
81
|
-
emit(event);
|
|
82
|
-
trigger(target, Symbol.iterator);
|
|
83
|
-
if (oldSize !== newSize) {
|
|
84
|
-
trigger(target, 'size');
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
return methodCache[prop];
|
|
88
|
-
}
|
|
89
|
-
if (prop === 'has') {
|
|
90
|
-
track(target, Symbol.iterator);
|
|
91
|
-
methodCache[prop] = function (value) {
|
|
92
|
-
// track specific primitive value when 'has' is called
|
|
93
|
-
// tracking object values for existence is complex and less common, handled by iteration track
|
|
94
|
-
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'symbol') {
|
|
95
|
-
track(target, String(value));
|
|
96
|
-
}
|
|
97
|
-
return target.has(value);
|
|
98
|
-
}.bind(target); // bind is still okay here, doesn't interfere with caching
|
|
99
|
-
return methodCache[prop];
|
|
100
|
-
}
|
|
101
|
-
// handle iteration methods
|
|
102
|
-
if (prop === 'values' || prop === Symbol.iterator || prop === 'entries' || prop === 'keys' || prop === 'forEach') {
|
|
103
|
-
track(target, Symbol.iterator);
|
|
104
|
-
const originalMethod = Reflect.get(target, prop, receiver);
|
|
105
|
-
// return custom iterators/foreach that wrap values during iteration
|
|
106
|
-
if (prop === 'forEach') {
|
|
107
|
-
methodCache[prop] = (callbackfn, thisArg) => {
|
|
108
|
-
// use the proxied values() to ensure values passed to callback are wrapped and tracked
|
|
109
|
-
const valuesIterator = proxy.values();
|
|
110
|
-
for (const value of valuesIterator) {
|
|
111
|
-
callbackfn.call(thisArg, value, value, proxy);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
return methodCache[prop];
|
|
115
|
-
}
|
|
116
|
-
// handle symbol.iterator, values, keys, entries by creating generator functions
|
|
117
|
-
methodCache[prop] = function* (...args) {
|
|
118
|
-
let index = 0; // use index for path generation if value is not primitive
|
|
119
|
-
const iterator = originalMethod.apply(target, args);
|
|
120
|
-
for (const entry of iterator) {
|
|
121
|
-
let valueToWrap = entry;
|
|
122
|
-
let mapKey = undefined; // key for entries() which yields [value, value]
|
|
123
|
-
if (prop === 'entries') {
|
|
124
|
-
mapKey = entry[0]; // for Set.entries(), key and value are the same
|
|
125
|
-
valueToWrap = entry[1];
|
|
126
|
-
}
|
|
127
|
-
track(target, String(index));
|
|
128
|
-
let wrappedValue = valueToWrap;
|
|
129
|
-
if (valueToWrap && typeof valueToWrap === 'object') {
|
|
130
|
-
const cachedValueProxy = wrapperCache.get(valueToWrap);
|
|
131
|
-
if (cachedValueProxy) {
|
|
132
|
-
wrappedValue = cachedValueProxy;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
// calculate path using index as key, as set values don't have inherent keys
|
|
136
|
-
const keyForPath = String(index);
|
|
137
|
-
const pathKey = path.length > 0 ? `${path.join('.')}.${keyForPath}` : keyForPath;
|
|
138
|
-
let newPath = getPathConcat(pathKey);
|
|
139
|
-
if (newPath === undefined) {
|
|
140
|
-
newPath = path.concat(keyForPath);
|
|
141
|
-
setPathConcat(pathKey, newPath);
|
|
142
|
-
}
|
|
143
|
-
// recursively wrap nested structures
|
|
144
|
-
if (valueToWrap instanceof Map)
|
|
145
|
-
wrappedValue = wrapMap(valueToWrap, emit, newPath);
|
|
146
|
-
else if (valueToWrap instanceof Set)
|
|
147
|
-
wrappedValue = wrapSet(valueToWrap, emit, newPath);
|
|
148
|
-
else if (Array.isArray(valueToWrap))
|
|
149
|
-
wrappedValue = wrapArray(valueToWrap, emit, newPath);
|
|
150
|
-
else if (valueToWrap instanceof Date)
|
|
151
|
-
wrappedValue = new Date(valueToWrap.getTime()); // dates are not proxied, return copy
|
|
152
|
-
else
|
|
153
|
-
wrappedValue = reactive(valueToWrap, emit, newPath);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (prop === 'entries') {
|
|
157
|
-
yield [wrappedValue, wrappedValue]; // set entries yield [value, value]
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
yield wrappedValue;
|
|
161
|
-
}
|
|
162
|
-
index++;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
return methodCache[prop];
|
|
166
|
-
}
|
|
167
|
-
if (prop === 'size') {
|
|
168
|
-
track(target, 'size');
|
|
169
|
-
return target.size;
|
|
170
|
-
}
|
|
171
|
-
const value = Reflect.get(target, prop, receiver);
|
|
172
|
-
// Bind plain functions accessed directly (e.g., toString)
|
|
173
|
-
if (typeof value === 'function') {
|
|
174
|
-
return value.bind(target);
|
|
175
|
-
}
|
|
176
|
-
return value;
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
// cache the newly created proxy before returning
|
|
180
|
-
wrapperCache.set(set, proxy);
|
|
181
|
-
return proxy;
|
|
182
|
-
}
|
package/dist/wrapArray.d.ts
DELETED