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