aoye 0.0.6 → 0.0.7

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/aoye.cjs.js CHANGED
@@ -2,30 +2,34 @@
2
2
 
3
3
  var bobeShared = require('bobe-shared');
4
4
 
5
- const evt = new bobeShared.BaseEvent();
5
+ new bobeShared.BaseEvent();
6
6
  const G = {
7
7
  /** 原子 signal 更新次数 */
8
8
  version: 0,
9
9
  id: 0,
10
10
  /** scope 销毁任务序号 */
11
11
  scopeDisposeI: 0,
12
- PullingSignal: null
12
+ PullingSignal: null,
13
+ /** 表示当前处于 pull 递归中 */
14
+ PullingRecurseDeep: 0
13
15
  };
14
- const dirtyLeafs = new bobeShared.SortMap();
16
+ new bobeShared.SortMap();
15
17
  var State = /* @__PURE__ */ ((State2) => {
16
18
  State2[State2["Clean"] = 0] = "Clean";
17
- State2[State2["LinkScopeOnly"] = 64] = "LinkScopeOnly";
18
- State2[State2["ScopeAbort"] = 32] = "ScopeAbort";
19
- State2[State2["ScopeReady"] = 16] = "ScopeReady";
20
- State2[State2["IsScope"] = 8] = "IsScope";
19
+ State2[State2["LinkScopeOnly"] = 256] = "LinkScopeOnly";
20
+ State2[State2["ScopeAbort"] = 128] = "ScopeAbort";
21
+ State2[State2["ScopeReady"] = 64] = "ScopeReady";
22
+ State2[State2["IsScope"] = 32] = "IsScope";
23
+ State2[State2["PullingDirty"] = 16] = "PullingDirty";
24
+ State2[State2["PullingUnknown"] = 8] = "PullingUnknown";
21
25
  State2[State2["Unknown"] = 4] = "Unknown";
22
26
  State2[State2["Dirty"] = 2] = "Dirty";
23
- State2[State2["Check"] = 1] = "Check";
27
+ State2[State2["Pulling"] = 1] = "Pulling";
24
28
  return State2;
25
29
  })(State || {});
26
30
  const DirtyState = 4 /* Unknown */ | 2 /* Dirty */;
27
- const ScopeExecuted = 16 /* ScopeReady */ | 32 /* ScopeAbort */;
28
- const ScopeAbort = 32 /* ScopeAbort */;
31
+ const ScopeExecuted = 64 /* ScopeReady */ | 128 /* ScopeAbort */;
32
+ const ScopeAbort = 128 /* ScopeAbort */;
29
33
 
30
34
  const leakI = (y, max) => y < 0 || y >= max ? null : y;
31
35
  const getLeft = (x, max) => leakI(x * 2 + 1, max);
@@ -130,6 +134,26 @@ class PriorityQueue {
130
134
  }
131
135
  }
132
136
 
137
+ var __defProp$2 = Object.defineProperty;
138
+ var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
139
+ var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
140
+ var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
141
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
142
+ var __spreadValues$2 = (a, b) => {
143
+ for (var prop in b || (b = {}))
144
+ if (__hasOwnProp$3.call(b, prop))
145
+ __defNormalProp$2(a, prop, b[prop]);
146
+ if (__getOwnPropSymbols$3)
147
+ for (var prop of __getOwnPropSymbols$3(b)) {
148
+ if (__propIsEnum$3.call(b, prop))
149
+ __defNormalProp$2(a, prop, b[prop]);
150
+ }
151
+ return a;
152
+ };
153
+ const DefaultTaskControlReturn = {
154
+ finished: true,
155
+ startNewCallbackAble: true
156
+ };
133
157
  class TaskQueue {
134
158
  constructor(callbackAble, aIsUrgent) {
135
159
  this.callbackAble = callbackAble;
@@ -153,18 +177,19 @@ class TaskQueue {
153
177
  const { taskQueue } = this;
154
178
  const fn = taskQueue.peek();
155
179
  if (!fn) return this.isScheduling = false;
156
- const hasRemain = fn();
157
- if (hasRemain) {
158
- this.callbackAble(this.scheduleTask.bind(this));
159
- return;
180
+ let info = fn() || {};
181
+ info = __spreadValues$2(__spreadValues$2({}, DefaultTaskControlReturn), info);
182
+ if (info.finished) {
183
+ taskQueue.poll();
184
+ if (taskQueue.size() === 0) {
185
+ return this.isScheduling = false;
186
+ }
160
187
  }
161
- taskQueue.poll();
162
- evt.emit("one", fn);
163
- if (taskQueue.size() === 0) {
164
- evt.emit("done", fn);
165
- return this.isScheduling = false;
188
+ if (info.startNewCallbackAble) {
189
+ this.callbackAble(this.scheduleTask.bind(this));
190
+ } else {
191
+ this.scheduleTask();
166
192
  }
167
- this.callbackAble(this.scheduleTask.bind(this));
168
193
  }
169
194
  }
170
195
 
@@ -192,40 +217,88 @@ const micro = (cb) => {
192
217
  p.then(cb);
193
218
  };
194
219
 
195
- var Scheduler = /* @__PURE__ */ ((Scheduler2) => {
196
- Scheduler2["Sync"] = "__Sync_";
197
- Scheduler2["Layout"] = "__Layout_";
198
- Scheduler2["Micro"] = "__Micro_";
199
- Scheduler2["Macro"] = "__Macro_";
200
- return Scheduler2;
201
- })(Scheduler || {});
202
- const _scheduler = {
203
- ["__Sync_" /* Sync */]: defaultScheduler,
204
- ["__Micro_" /* Micro */]: microScheduler,
205
- ["__Macro_" /* Macro */]: macroScheduler,
206
- ["__Layout_" /* Layout */]: layoutScheduler
207
- };
208
- const scheduler = (key, value) => _scheduler[key] = value;
209
- function defaultScheduler(effects) {
210
- for (const effect of effects) {
211
- effect.runIfDirty();
220
+ class Scheduler {
221
+ constructor() {
222
+ this.effectQueue = new bobeShared.Queue();
223
+ }
224
+ addEffect(effect) {
225
+ var _a;
226
+ const item = this.effectQueue.push(effect);
227
+ (_a = this.onEffectAdded) == null ? void 0 : _a.call(this, effect, item, this.effectQueue);
228
+ return item;
229
+ }
230
+ }
231
+ Scheduler.Sync = "__Sync_";
232
+ Scheduler.Layout = "__Layout_";
233
+ Scheduler.Micro = "__Micro_";
234
+ Scheduler.Macro = "__Macro_";
235
+ class SyncScheduler extends Scheduler {
236
+ onOneSetEffectsAdded(subQueue, queue) {
237
+ subQueue.forEach((effect, item) => {
238
+ effect.runIfDirty();
239
+ subQueue.delete(item);
240
+ });
212
241
  }
213
242
  }
214
- let microSTaskQueue;
215
- let macroSTaskQueue;
216
- let layoutSTaskQueue;
217
- function microScheduler(effects) {
218
- microSTaskQueue = microSTaskQueue || TaskQueue.create({ callbackAble: micro, aIsUrgent: (a, b) => a.time < b.time });
219
- microSTaskQueue.pushTask(defaultScheduler.bind(null, effects));
243
+ class MicroScheduler extends Scheduler {
244
+ constructor() {
245
+ super(...arguments);
246
+ this.taskQueue = TaskQueue.create({ callbackAble: micro, aIsUrgent: (a, b) => a.time < b.time });
247
+ }
248
+ onOneSetEffectsAdded(subQueue, queue) {
249
+ const task = () => {
250
+ subQueue.forEach((effect, item) => {
251
+ effect.runIfDirty();
252
+ subQueue.delete(item);
253
+ });
254
+ return {
255
+ finished: true,
256
+ startNewCallbackAble: false
257
+ };
258
+ };
259
+ task.time = Date.now();
260
+ this.taskQueue.pushTask(task);
261
+ }
220
262
  }
221
- function macroScheduler(effects) {
222
- macroSTaskQueue = macroSTaskQueue || TaskQueue.create({ callbackAble: macro, aIsUrgent: (a, b) => a.time < b.time });
223
- macroSTaskQueue.pushTask(defaultScheduler.bind(null, effects));
263
+ class MacroScheduler extends Scheduler {
264
+ constructor() {
265
+ super(...arguments);
266
+ this.taskQueue = TaskQueue.create({ callbackAble: macro, aIsUrgent: (a, b) => a.time < b.time });
267
+ }
268
+ onOneSetEffectsAdded(subQueue, queue) {
269
+ const task = () => {
270
+ subQueue.forEach((effect, item) => {
271
+ effect.runIfDirty();
272
+ subQueue.delete(item);
273
+ });
274
+ };
275
+ task.time = Date.now();
276
+ this.taskQueue.pushTask(task);
277
+ }
224
278
  }
225
- function layoutScheduler(effects) {
226
- layoutSTaskQueue = layoutSTaskQueue || TaskQueue.create({ callbackAble: macro, aIsUrgent: (a, b) => a.time < b.time });
227
- layoutSTaskQueue.pushTask(defaultScheduler.bind(null, effects));
279
+ class LayoutScheduler extends Scheduler {
280
+ constructor() {
281
+ super(...arguments);
282
+ this.taskQueue = TaskQueue.create({ callbackAble: macro, aIsUrgent: (a, b) => a.time < b.time });
283
+ }
284
+ onOneSetEffectsAdded(subQueue, queue) {
285
+ const task = () => {
286
+ subQueue.forEach((effect, item) => {
287
+ effect.runIfDirty();
288
+ subQueue.delete(item);
289
+ });
290
+ };
291
+ task.time = Date.now();
292
+ this.taskQueue.pushTask(task);
293
+ }
228
294
  }
295
+ const _scheduler = {
296
+ [Scheduler.Sync]: new SyncScheduler(),
297
+ [Scheduler.Micro]: new MicroScheduler(),
298
+ [Scheduler.Macro]: new MacroScheduler(),
299
+ [Scheduler.Layout]: new LayoutScheduler()
300
+ };
301
+ const registerScheduler = (key, Ctor) => _scheduler[key] = new Ctor();
229
302
 
230
303
  var __defProp$1 = Object.defineProperty;
231
304
  var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
@@ -558,32 +631,46 @@ var __objRest = (source, exclude) => {
558
631
  return target;
559
632
  };
560
633
  const markDeep = (signal) => {
561
- let level = 0;
634
+ let level = 0, firstEffectItem, lastEffectItem, updatedSchedulers = /* @__PURE__ */ new Set();
562
635
  dfs(signal, {
563
636
  isUp: false,
564
637
  begin: ({ node }) => {
565
- if (node.state & (State.Check | State.Unknown | State.Dirty) || node.isDisabled()) {
638
+ if (node.isDisabled()) {
566
639
  return true;
567
640
  }
641
+ const inPullingArea = node.state & State.Pulling;
642
+ const Unknown = inPullingArea ? State.PullingUnknown : State.Unknown;
568
643
  const isEffect = level > 0;
569
644
  const isLeaf = !node.emitStart || node.emitStart.downstream === node.scope;
570
645
  if (isEffect) {
571
- node.state |= State.Unknown;
646
+ node.state |= Unknown;
572
647
  } else if (!isLeaf) {
573
648
  node.state |= State.Dirty;
574
649
  }
575
- if (isLeaf && isEffect) {
576
- dirtyLeafs.add(node.scheduler, node);
650
+ if (isLeaf && isEffect && !inPullingArea) {
651
+ const key = node.scheduler;
652
+ const instance = _scheduler[key];
653
+ const item = instance.addEffect(node);
654
+ if (!firstEffectItem) {
655
+ firstEffectItem = item;
656
+ }
657
+ lastEffectItem = item;
658
+ updatedSchedulers.add(key);
577
659
  }
578
660
  level++;
579
661
  }
580
662
  });
581
- for (const key in dirtyLeafs.data) {
582
- const effects = dirtyLeafs.data[key];
583
- const scheduler = _scheduler[key];
584
- scheduler(effects);
663
+ for (const key of updatedSchedulers) {
664
+ const instance = _scheduler[key];
665
+ instance == null ? void 0 : instance.onOneSetEffectsAdded(instance.effectQueue.subRef(firstEffectItem, lastEffectItem), instance.effectQueue);
666
+ }
667
+ };
668
+ const pullingPostprocess = (node) => {
669
+ node.state &= ~State.Pulling;
670
+ if (node.state & State.PullingUnknown) {
671
+ node.state &= ~State.PullingUnknown;
672
+ node.state |= State.Unknown;
585
673
  }
586
- dirtyLeafs.clear();
587
674
  };
588
675
  const _Signal = class _Signal {
589
676
  constructor(nextValue, customPull) {
@@ -623,6 +710,7 @@ const _Signal = class _Signal {
623
710
  */
624
711
  pullRecurse(shouldLink = true) {
625
712
  var _a, _b;
713
+ G.PullingRecurseDeep++;
626
714
  let downstream = G.PullingSignal;
627
715
  const isScope = this.state & State.IsScope;
628
716
  if (
@@ -638,6 +726,7 @@ const _Signal = class _Signal {
638
726
  return this.value;
639
727
  }
640
728
  this.recEnd = null;
729
+ this.state |= State.Pulling;
641
730
  G.PullingSignal = this;
642
731
  (_a = this.clean) == null ? void 0 : _a.call(this);
643
732
  this.clean = null;
@@ -655,9 +744,11 @@ const _Signal = class _Signal {
655
744
  console.error("\u8BA1\u7B97\u5C5E\u6027\u62A5\u9519\u8FD9\u6B21\u4E0D\u89E6\u53D1\uFF0C\u540E\u7EED\u72B6\u6001\u53EF\u80FD\u51FA\u9519", error);
656
745
  return this.value;
657
746
  } finally {
747
+ pullingPostprocess(this);
658
748
  const toDel = (_b = this.recEnd) == null ? void 0 : _b.nextRecLine;
659
749
  unlinkRecWithScope(toDel);
660
750
  G.PullingSignal = downstream;
751
+ G.PullingRecurseDeep--;
661
752
  }
662
753
  }
663
754
  pullDeep() {
@@ -668,10 +759,10 @@ const _Signal = class _Signal {
668
759
  dfs(signal, {
669
760
  isUp: true,
670
761
  begin: ({ node }) => {
671
- if (node.state & State.Check || !(node.state & DirtyState) || node.isDisabled()) {
762
+ if (node.state & State.Pulling || !(node.state & DirtyState) || node.isDisabled()) {
672
763
  return true;
673
764
  }
674
- node.state |= State.Check;
765
+ node.state |= State.Pulling;
675
766
  },
676
767
  complete: ({ node, notGoDeep: currentClean, walkedLine }) => {
677
768
  let noGoSibling = false;
@@ -681,7 +772,7 @@ const _Signal = class _Signal {
681
772
  if (!node.recStart && node.value !== node.nextValue) {
682
773
  node.markDownStreamsDirty();
683
774
  node.state &= ~State.Dirty;
684
- node.state &= ~State.Check;
775
+ node.state &= ~State.Pulling;
685
776
  return;
686
777
  } else {
687
778
  const prevPulling = G.PullingSignal;
@@ -699,7 +790,7 @@ const _Signal = class _Signal {
699
790
  node.state &= ~State.Unknown;
700
791
  }
701
792
  node.version = G.version;
702
- node.state &= ~State.Check;
793
+ pullingPostprocess(node);
703
794
  return noGoSibling;
704
795
  }
705
796
  });
@@ -738,6 +829,7 @@ const _Signal = class _Signal {
738
829
  G.version++;
739
830
  markDeep(this);
740
831
  }
832
+ /** 返回值为 true 表示已处理 */
741
833
  runIfDirty() {
742
834
  this.state & (State.Unknown | State.Dirty) && this.v;
743
835
  }
@@ -752,6 +844,54 @@ const _Signal = class _Signal {
752
844
  _Signal.Pulling = null;
753
845
  let Signal = _Signal;
754
846
 
847
+ var Keys = /* @__PURE__ */ ((Keys2) => {
848
+ Keys2["Iterator"] = "__Aoye_Iterator";
849
+ Keys2["Raw"] = "__Aoye_Raw";
850
+ return Keys2;
851
+ })(Keys || {});
852
+
853
+ const proxyMap = /* @__PURE__ */ new WeakMap();
854
+ const deepSignal = (target, deep = true) => {
855
+ const isObj = typeof target === "object" && target !== null;
856
+ if (!isObj) return target;
857
+ if (proxyMap.has(target)) return proxyMap.get(target);
858
+ const cells = /* @__PURE__ */ new Map();
859
+ const proxy = new Proxy(target, {
860
+ get(obj, prop, receiver) {
861
+ if (prop === Keys.Raw) {
862
+ return target;
863
+ }
864
+ if (cells.has(prop)) {
865
+ return cells.get(prop).v;
866
+ }
867
+ const value = Reflect.get(obj, prop, receiver);
868
+ const wrappedValue = deep ? deepSignal(value) : value;
869
+ const s = Signal.create(wrappedValue, {
870
+ scheduler: Scheduler.Sync,
871
+ isScope: false
872
+ });
873
+ cells.set(prop, s);
874
+ return s.v;
875
+ },
876
+ set(obj, prop, value, receiver) {
877
+ if (cells.has(prop)) {
878
+ const cell = cells.get(prop);
879
+ cell.v = deep ? deepSignal(value) : value;
880
+ }
881
+ return Reflect.set(obj, prop, value, receiver);
882
+ },
883
+ // 【核心修改】拦截 delete 操作
884
+ deleteProperty(obj, prop) {
885
+ if (cells.has(prop)) {
886
+ cells.delete(prop);
887
+ }
888
+ return Reflect.deleteProperty(obj, prop);
889
+ }
890
+ });
891
+ proxyMap.set(target, proxy);
892
+ return proxy;
893
+ };
894
+
755
895
  var __defProp = Object.defineProperty;
756
896
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
757
897
  var __hasOwnProp = Object.prototype.hasOwnProperty;
@@ -768,13 +908,26 @@ var __spreadValues = (a, b) => {
768
908
  }
769
909
  return a;
770
910
  };
911
+ const DefaultCustomSignalOpt = {
912
+ /** 三种模式
913
+ * 1. auto: 根据值类型自动判断 默认
914
+ * 2. ref: 对任何值使用 {v: xxx} 进行包装
915
+ * 3. proxy: 使用 proxy 进行包装
916
+ */
917
+ mode: "auto",
918
+ /** 是否深度响应式 */
919
+ deep: true
920
+ };
771
921
  ({
772
922
  scheduler: Scheduler.Sync});
773
- const $ = (init) => {
923
+ const $ = (init, opt = {}) => {
924
+ opt = __spreadValues(__spreadValues({}, DefaultCustomSignalOpt), opt);
774
925
  let intiValue, customPull;
775
- if (init instanceof Function) {
926
+ if (typeof init === "function") {
776
927
  intiValue = null;
777
928
  customPull = init;
929
+ } else if (opt.mode !== "ref" && typeof init === "object" && init !== null) {
930
+ return deepSignal(init, opt.deep);
778
931
  } else {
779
932
  intiValue = init;
780
933
  }
@@ -843,14 +996,23 @@ const customEffect = (opt) => {
843
996
  return effect(init, __spreadValues(__spreadValues({}, opt), innerOpt));
844
997
  });
845
998
  };
999
+ const isSignal = (value) => {
1000
+ return value instanceof Signal;
1001
+ };
1002
+ const isScope = (value) => {
1003
+ return value instanceof Signal;
1004
+ };
846
1005
 
847
1006
  exports.$ = $;
1007
+ exports.Keys = Keys;
848
1008
  exports.Scheduler = Scheduler;
849
1009
  exports.TaskQueue = TaskQueue;
850
1010
  exports.clean = clean;
851
1011
  exports.customEffect = customEffect;
852
1012
  exports.effect = effect;
1013
+ exports.isScope = isScope;
1014
+ exports.isSignal = isSignal;
1015
+ exports.registerScheduler = registerScheduler;
853
1016
  exports.runWithPulling = runWithPulling;
854
- exports.scheduler = scheduler;
855
1017
  exports.scope = scope;
856
1018
  //# sourceMappingURL=aoye.cjs.js.map