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