j20 0.0.21 → 0.0.22
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.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -123
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
// 当前正在执行的effect或computed
|
|
2
1
|
let currentReaction = null;
|
|
3
|
-
// 批处理栈,用于延迟 effect 的执行
|
|
4
2
|
let batchDepth = 0;
|
|
5
|
-
// 待执行的 effect 队列
|
|
6
3
|
let pendingEffects = new Set();
|
|
7
|
-
// 存储所有信号的依赖关系
|
|
8
4
|
const depMap = new WeakMap();
|
|
9
|
-
/**
|
|
10
|
-
* Signal类 - 用于存储响应式数据
|
|
11
|
-
*/
|
|
12
5
|
class Signal {
|
|
13
6
|
SIGNAL = true;
|
|
14
7
|
_value;
|
|
@@ -18,7 +11,6 @@ class Signal {
|
|
|
18
11
|
this._value = value;
|
|
19
12
|
}
|
|
20
13
|
get value() {
|
|
21
|
-
// 如果有当前正在执行的reaction,建立依赖关系
|
|
22
14
|
if (currentReaction) {
|
|
23
15
|
this.track(currentReaction);
|
|
24
16
|
}
|
|
@@ -29,21 +21,19 @@ class Signal {
|
|
|
29
21
|
return;
|
|
30
22
|
this._value = newValue;
|
|
31
23
|
this._version++;
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
if (this._deps.size === 0)
|
|
25
|
+
return;
|
|
26
|
+
const deps = Array.from(this._deps);
|
|
27
|
+
deps.forEach((reaction) => {
|
|
34
28
|
if (reaction instanceof Computed) {
|
|
35
29
|
reaction.markDirty();
|
|
36
30
|
}
|
|
37
31
|
else if (reaction.isActive()) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
reaction.execute();
|
|
46
|
-
}
|
|
32
|
+
if (batchDepth > 0) {
|
|
33
|
+
pendingEffects.add(reaction);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
reaction.execute();
|
|
47
37
|
}
|
|
48
38
|
}
|
|
49
39
|
});
|
|
@@ -51,25 +41,19 @@ class Signal {
|
|
|
51
41
|
get version() {
|
|
52
42
|
return this._version;
|
|
53
43
|
}
|
|
54
|
-
// 建立依赖关系
|
|
55
44
|
track(reaction) {
|
|
56
45
|
if (!this._deps.has(reaction)) {
|
|
57
46
|
this._deps.add(reaction);
|
|
58
|
-
// 维护反向依赖关系
|
|
59
47
|
let reactions = depMap.get(this);
|
|
60
48
|
if (!reactions) {
|
|
61
49
|
reactions = new Set();
|
|
62
50
|
depMap.set(this, reactions);
|
|
63
51
|
}
|
|
64
52
|
reactions.add(reaction);
|
|
65
|
-
// 在reaction中记录依赖
|
|
66
|
-
reaction.track(this);
|
|
67
53
|
}
|
|
54
|
+
reaction.track(this);
|
|
68
55
|
}
|
|
69
56
|
}
|
|
70
|
-
/**
|
|
71
|
-
* Computed类 - 用于计算派生值
|
|
72
|
-
*/
|
|
73
57
|
class Computed {
|
|
74
58
|
SIGNAL = true;
|
|
75
59
|
computeFn;
|
|
@@ -81,7 +65,6 @@ class Computed {
|
|
|
81
65
|
sources = new Set();
|
|
82
66
|
constructor(computeFn) {
|
|
83
67
|
this.computeFn = computeFn;
|
|
84
|
-
// 使用symbol作为初始值占位符
|
|
85
68
|
this._value = undefined;
|
|
86
69
|
}
|
|
87
70
|
get value() {
|
|
@@ -91,12 +74,11 @@ class Computed {
|
|
|
91
74
|
if (this.dirty) {
|
|
92
75
|
this.compute();
|
|
93
76
|
}
|
|
94
|
-
// 建立依赖关系
|
|
95
77
|
if (currentReaction) {
|
|
96
78
|
if (!this._deps.has(currentReaction)) {
|
|
97
79
|
this._deps.add(currentReaction);
|
|
98
|
-
currentReaction.track(this);
|
|
99
80
|
}
|
|
81
|
+
currentReaction.track(this);
|
|
100
82
|
}
|
|
101
83
|
return this._value;
|
|
102
84
|
}
|
|
@@ -107,17 +89,14 @@ class Computed {
|
|
|
107
89
|
if (this.disposed) {
|
|
108
90
|
throw new Error("Cannot compute disposed computed");
|
|
109
91
|
}
|
|
110
|
-
|
|
111
|
-
if (computationStack.includes(this)) {
|
|
92
|
+
if (computationStack.has(this)) {
|
|
112
93
|
throw new Error("Circular dependency detected in computed values");
|
|
113
94
|
}
|
|
114
95
|
this.dirty = false;
|
|
115
|
-
// 保存当前状态
|
|
116
96
|
const prevReaction = currentReaction;
|
|
117
97
|
const prevSources = this.sources;
|
|
118
98
|
this.sources = new Set();
|
|
119
|
-
|
|
120
|
-
computationStack.push(this);
|
|
99
|
+
computationStack.add(this);
|
|
121
100
|
currentReaction = this;
|
|
122
101
|
try {
|
|
123
102
|
this._value = this.computeFn();
|
|
@@ -128,19 +107,15 @@ class Computed {
|
|
|
128
107
|
throw e;
|
|
129
108
|
}
|
|
130
109
|
finally {
|
|
131
|
-
|
|
132
|
-
const index = computationStack.indexOf(this);
|
|
133
|
-
if (index !== -1) {
|
|
134
|
-
computationStack.splice(index, 1);
|
|
135
|
-
}
|
|
110
|
+
computationStack.delete(this);
|
|
136
111
|
currentReaction = prevReaction;
|
|
137
|
-
// 清理不再依赖的sources
|
|
138
112
|
prevSources.forEach((source) => {
|
|
139
113
|
if (!this.sources.has(source)) {
|
|
140
114
|
const reactions = depMap.get(source);
|
|
141
115
|
if (reactions) {
|
|
142
116
|
reactions.delete(this);
|
|
143
117
|
}
|
|
118
|
+
source._deps.delete(this);
|
|
144
119
|
}
|
|
145
120
|
});
|
|
146
121
|
}
|
|
@@ -149,14 +124,15 @@ class Computed {
|
|
|
149
124
|
if (this.disposed || this.dirty)
|
|
150
125
|
return;
|
|
151
126
|
this.dirty = true;
|
|
152
|
-
|
|
153
|
-
|
|
127
|
+
if (this._deps.size === 0)
|
|
128
|
+
return;
|
|
129
|
+
const deps = Array.from(this._deps);
|
|
130
|
+
deps.forEach((reaction) => {
|
|
154
131
|
if (reaction instanceof Computed) {
|
|
155
132
|
reaction.markDirty();
|
|
156
133
|
}
|
|
157
134
|
else if (reaction.isActive()) {
|
|
158
135
|
if (batchDepth > 0) {
|
|
159
|
-
// 在批处理模式下,延迟执行 effect
|
|
160
136
|
pendingEffects.add(reaction);
|
|
161
137
|
}
|
|
162
138
|
else {
|
|
@@ -168,52 +144,37 @@ class Computed {
|
|
|
168
144
|
track(source) {
|
|
169
145
|
if (this.disposed)
|
|
170
146
|
return;
|
|
171
|
-
|
|
172
|
-
this.sources.add(source);
|
|
173
|
-
let reactions = depMap.get(source);
|
|
174
|
-
if (!reactions) {
|
|
175
|
-
reactions = new Set();
|
|
176
|
-
depMap.set(source, reactions);
|
|
177
|
-
}
|
|
178
|
-
reactions.add(this);
|
|
179
|
-
}
|
|
147
|
+
this.sources.add(source);
|
|
180
148
|
}
|
|
181
149
|
dispose() {
|
|
182
150
|
if (this.disposed)
|
|
183
151
|
return;
|
|
184
152
|
this.disposed = true;
|
|
185
|
-
// 清理所有依赖关系
|
|
186
153
|
this.sources.forEach((source) => {
|
|
187
154
|
const reactions = depMap.get(source);
|
|
188
155
|
if (reactions) {
|
|
189
156
|
reactions.delete(this);
|
|
190
157
|
}
|
|
158
|
+
source._deps.delete(this);
|
|
191
159
|
});
|
|
192
160
|
this.sources.clear();
|
|
193
161
|
this._deps.clear();
|
|
194
|
-
// 清理引用
|
|
195
162
|
this._value = undefined;
|
|
196
163
|
this.computeFn = undefined;
|
|
197
164
|
}
|
|
198
165
|
}
|
|
199
|
-
|
|
200
|
-
const computationStack = [];
|
|
201
|
-
/**
|
|
202
|
-
* Effect类 - 用于执行副作用
|
|
203
|
-
*/
|
|
166
|
+
const computationStack = new Set();
|
|
204
167
|
class Effect {
|
|
205
168
|
effectFn;
|
|
206
169
|
cleanupFn = null;
|
|
207
170
|
disposed = false;
|
|
208
171
|
_deps = new Set();
|
|
209
|
-
_depVersions = new Map();
|
|
210
172
|
constructor(effectFn) {
|
|
211
173
|
this.effectFn = effectFn;
|
|
212
174
|
}
|
|
213
175
|
execute() {
|
|
214
176
|
if (this.disposed)
|
|
215
177
|
return;
|
|
216
|
-
// 执行清理函数
|
|
217
178
|
if (this.cleanupFn) {
|
|
218
179
|
try {
|
|
219
180
|
this.cleanupFn();
|
|
@@ -223,7 +184,14 @@ class Effect {
|
|
|
223
184
|
}
|
|
224
185
|
this.cleanupFn = null;
|
|
225
186
|
}
|
|
226
|
-
|
|
187
|
+
this._deps.forEach((dep) => {
|
|
188
|
+
const reactions = depMap.get(dep);
|
|
189
|
+
if (reactions) {
|
|
190
|
+
reactions.delete(this);
|
|
191
|
+
}
|
|
192
|
+
dep._deps.delete(this);
|
|
193
|
+
});
|
|
194
|
+
this._deps.clear();
|
|
227
195
|
const prevReaction = currentReaction;
|
|
228
196
|
currentReaction = this;
|
|
229
197
|
try {
|
|
@@ -240,16 +208,14 @@ class Effect {
|
|
|
240
208
|
if (this.disposed)
|
|
241
209
|
return;
|
|
242
210
|
this.disposed = true;
|
|
243
|
-
// 清理所有依赖关系
|
|
244
211
|
this._deps.forEach((dep) => {
|
|
245
212
|
const reactions = depMap.get(dep);
|
|
246
213
|
if (reactions) {
|
|
247
214
|
reactions.delete(this);
|
|
248
215
|
}
|
|
216
|
+
dep._deps.delete(this);
|
|
249
217
|
});
|
|
250
218
|
this._deps.clear();
|
|
251
|
-
this._depVersions.clear();
|
|
252
|
-
// 执行清理函数
|
|
253
219
|
if (this.cleanupFn) {
|
|
254
220
|
try {
|
|
255
221
|
this.cleanupFn();
|
|
@@ -266,44 +232,20 @@ class Effect {
|
|
|
266
232
|
track(source) {
|
|
267
233
|
if (this.disposed)
|
|
268
234
|
return;
|
|
269
|
-
|
|
270
|
-
this._deps.add(source);
|
|
271
|
-
// 记录依赖的版本号
|
|
272
|
-
if ("version" in source) {
|
|
273
|
-
this._depVersions.set(source, source.version);
|
|
274
|
-
}
|
|
275
|
-
let reactions = depMap.get(source);
|
|
276
|
-
if (!reactions) {
|
|
277
|
-
reactions = new Set();
|
|
278
|
-
depMap.set(source, reactions);
|
|
279
|
-
}
|
|
280
|
-
reactions.add(this);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
hasDepsChanged() {
|
|
284
|
-
for (const [dep, version] of this._depVersions) {
|
|
285
|
-
if ("version" in dep && dep.version !== version) {
|
|
286
|
-
return true;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return false;
|
|
235
|
+
this._deps.add(source);
|
|
290
236
|
}
|
|
291
237
|
}
|
|
292
|
-
// 创建信号
|
|
293
238
|
function signal(initialValue) {
|
|
294
239
|
return new Signal(initialValue);
|
|
295
240
|
}
|
|
296
|
-
// 创建计算值
|
|
297
241
|
function computed(computeFn) {
|
|
298
242
|
return new Computed(computeFn);
|
|
299
243
|
}
|
|
300
|
-
// 创建副作用
|
|
301
244
|
function effect$1(effectFn) {
|
|
302
245
|
const effectInstance = new Effect(effectFn);
|
|
303
246
|
effectInstance.execute();
|
|
304
247
|
return effectInstance;
|
|
305
248
|
}
|
|
306
|
-
// 临时取消追踪
|
|
307
249
|
function untrack(fn) {
|
|
308
250
|
const prevReaction = currentReaction;
|
|
309
251
|
currentReaction = null;
|
|
@@ -314,7 +256,6 @@ function untrack(fn) {
|
|
|
314
256
|
currentReaction = prevReaction;
|
|
315
257
|
}
|
|
316
258
|
}
|
|
317
|
-
// 批处理 - 延迟 effect 的执行直到批处理结束
|
|
318
259
|
function batch(fn) {
|
|
319
260
|
batchDepth++;
|
|
320
261
|
try {
|
|
@@ -322,14 +263,17 @@ function batch(fn) {
|
|
|
322
263
|
}
|
|
323
264
|
finally {
|
|
324
265
|
batchDepth--;
|
|
325
|
-
// 当批处理结束时,执行所有待处理的 effect
|
|
326
266
|
if (batchDepth === 0) {
|
|
327
267
|
const effects = Array.from(pendingEffects);
|
|
328
268
|
pendingEffects.clear();
|
|
329
|
-
// 执行所有待处理的 effect
|
|
330
269
|
effects.forEach((effect) => {
|
|
331
270
|
if (effect.isActive()) {
|
|
332
|
-
|
|
271
|
+
try {
|
|
272
|
+
effect.execute();
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
console.error(e);
|
|
276
|
+
}
|
|
333
277
|
}
|
|
334
278
|
});
|
|
335
279
|
}
|
|
@@ -479,14 +423,26 @@ const createDom = (tag, props, children) => {
|
|
|
479
423
|
const BRAND = "j20";
|
|
480
424
|
|
|
481
425
|
const isSignal = (a) => a?.SIGNAL === true;
|
|
426
|
+
const createStyleSheet = (css) => {
|
|
427
|
+
const sheet = new CSSStyleSheet();
|
|
428
|
+
sheet.replaceSync(css);
|
|
429
|
+
return sheet;
|
|
430
|
+
};
|
|
482
431
|
const addStyleSheet = (node, styleSheet) => {
|
|
483
|
-
if (node
|
|
432
|
+
if ("addStyleSheet" in node) {
|
|
433
|
+
node.addStyleSheet(styleSheet);
|
|
434
|
+
}
|
|
435
|
+
else if (node.adoptedStyleSheets &&
|
|
484
436
|
!node.adoptedStyleSheets.includes(styleSheet)) {
|
|
485
437
|
node.adoptedStyleSheets = [...node.adoptedStyleSheets, styleSheet];
|
|
486
438
|
}
|
|
487
439
|
};
|
|
488
440
|
const removeStyleSheet = (node, styleSheet) => {
|
|
489
|
-
if (
|
|
441
|
+
if ("removeStyleSheet" in node) {
|
|
442
|
+
node.removeStyleSheet(styleSheet);
|
|
443
|
+
}
|
|
444
|
+
else if (node.adoptedStyleSheets &&
|
|
445
|
+
node.adoptedStyleSheets.includes(styleSheet)) {
|
|
490
446
|
const newSet = new Set(node.adoptedStyleSheets);
|
|
491
447
|
newSet.delete(styleSheet);
|
|
492
448
|
node.adoptedStyleSheets = Array.from(newSet);
|
|
@@ -919,62 +875,57 @@ const refWeakMap = new WeakMap();
|
|
|
919
875
|
const createCss = (css) => {
|
|
920
876
|
const id = getId();
|
|
921
877
|
return () => {
|
|
922
|
-
const
|
|
878
|
+
const classNameId = `j_${id}`;
|
|
923
879
|
const replacedCss = css.replace(/\.(\w[\w-]*)\s*?\{/g, (_, className) => {
|
|
924
|
-
return `.${className}_${
|
|
880
|
+
return `.${className}_${classNameId} {`;
|
|
925
881
|
});
|
|
926
882
|
styleSheet(id, replacedCss);
|
|
927
883
|
return new Proxy({}, {
|
|
928
884
|
get: (_, prop) => {
|
|
929
|
-
return `${prop}_${
|
|
885
|
+
return `${prop}_${classNameId}`;
|
|
930
886
|
},
|
|
931
887
|
});
|
|
932
888
|
};
|
|
933
889
|
};
|
|
934
|
-
const addReference = (host, id,
|
|
890
|
+
const addReference = (host, id, css) => {
|
|
935
891
|
if (!refWeakMap.get(host)) {
|
|
936
892
|
refWeakMap.set(host, []);
|
|
937
893
|
}
|
|
938
894
|
const states = refWeakMap.get(host) ?? [];
|
|
939
895
|
const state = states.find((state) => state.id === id);
|
|
940
896
|
if (!state) {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
add();
|
|
897
|
+
const newState = {
|
|
898
|
+
id,
|
|
899
|
+
refCount: 1,
|
|
900
|
+
styleSheet: createStyleSheet(css),
|
|
901
|
+
};
|
|
902
|
+
refWeakMap.set(host, [...states, newState]);
|
|
903
|
+
addStyleSheet(host, newState.styleSheet);
|
|
949
904
|
}
|
|
950
905
|
else {
|
|
951
906
|
state.refCount++;
|
|
952
907
|
}
|
|
953
908
|
};
|
|
954
|
-
const removeReference = (host, id
|
|
909
|
+
const removeReference = (host, id) => {
|
|
955
910
|
const states = refWeakMap.get(host) ?? [];
|
|
956
911
|
const state = states.find((state) => state.id === id);
|
|
957
912
|
if (state) {
|
|
958
913
|
state.refCount--;
|
|
959
914
|
if (state.refCount === 0) {
|
|
960
|
-
remove();
|
|
961
915
|
refWeakMap.set(host, states.filter((state) => state.id !== id));
|
|
916
|
+
removeStyleSheet(host, state.styleSheet);
|
|
962
917
|
}
|
|
963
918
|
}
|
|
964
919
|
};
|
|
965
920
|
const styleSheet = (id, css) => {
|
|
966
921
|
let instance = getCurrentInstance();
|
|
967
|
-
const sheet = new CSSStyleSheet();
|
|
968
|
-
css && sheet.replaceSync(css);
|
|
969
922
|
let root;
|
|
970
923
|
while (instance) {
|
|
971
924
|
if (instance.host) {
|
|
972
925
|
const host = instance.host;
|
|
973
|
-
addReference(host, id,
|
|
974
|
-
host.addStyleSheet(sheet);
|
|
975
|
-
});
|
|
926
|
+
addReference(host, id, css);
|
|
976
927
|
onDestroy(() => {
|
|
977
|
-
removeReference(host, id
|
|
928
|
+
removeReference(host, id);
|
|
978
929
|
});
|
|
979
930
|
break;
|
|
980
931
|
}
|
|
@@ -992,16 +943,11 @@ const styleSheet = (id, css) => {
|
|
|
992
943
|
}
|
|
993
944
|
node = node.parentNode;
|
|
994
945
|
} while (node);
|
|
995
|
-
addReference(node, id,
|
|
996
|
-
addStyleSheet(node, sheet);
|
|
997
|
-
});
|
|
946
|
+
addReference(node, id, css);
|
|
998
947
|
onDestroy(() => {
|
|
999
|
-
removeReference(node, id
|
|
1000
|
-
removeStyleSheet(node, sheet);
|
|
1001
|
-
});
|
|
948
|
+
removeReference(node, id);
|
|
1002
949
|
});
|
|
1003
950
|
}
|
|
1004
|
-
return sheet;
|
|
1005
951
|
};
|
|
1006
952
|
|
|
1007
953
|
function insertAfter(parentNode, newNode, targetNode) {
|