aoye 0.0.1 → 0.0.4

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,122 +1,207 @@
1
- function Queue() {
2
- return {
3
- len: 0,
4
- push: Queue_$$$_push,
5
- shift: Queue_$$$_shift,
6
- get first() {
7
- var _a;
8
- return (_a = this._first) === null || _a === void 0 ? void 0 : _a.v;
9
- },
10
- get last() {
11
- var _a;
12
- return (_a = this._last) === null || _a === void 0 ? void 0 : _a.v;
1
+ import { BaseEvent, SortMap } from 'bobe-shared';
2
+
3
+ const evt = new BaseEvent();
4
+ const G = {
5
+ /** 原子 signal 更新次数 */
6
+ version: 0,
7
+ id: 0,
8
+ /** scope 销毁任务序号 */
9
+ scopeDisposeI: 0,
10
+ PullingSignal: null
11
+ };
12
+ const dirtyLeafs = new SortMap();
13
+ var State = /* @__PURE__ */ ((State2) => {
14
+ 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";
19
+ State2[State2["Unknown"] = 4] = "Unknown";
20
+ State2[State2["Dirty"] = 2] = "Dirty";
21
+ State2[State2["Check"] = 1] = "Check";
22
+ return State2;
23
+ })(State || {});
24
+ const DirtyState = 4 /* Unknown */ | 2 /* Dirty */;
25
+ const ScopeExecuted = 16 /* ScopeReady */ | 32 /* ScopeAbort */;
26
+ const ScopeAbort = 32 /* ScopeAbort */;
27
+
28
+ const leakI = (y, max) => y < 0 || y >= max ? null : y;
29
+ const getLeft = (x, max) => leakI(x * 2 + 1, max);
30
+ const getRight = (x, max) => leakI(x * 2 + 2, max);
31
+ const getParent = (x, max) => leakI(x - 1 >>> 1, max);
32
+ const exchange = (arr, i, j) => [arr[i], arr[j]] = [arr[j], arr[i]];
33
+ class PriorityQueue {
34
+ // 构造函数接受一个compare函数
35
+ // compare返回的-1, 0, 1决定元素是否优先被去除
36
+ constructor(aIsUrgent) {
37
+ this.aIsUrgent = aIsUrgent;
38
+ this.arr = [];
39
+ this.goUp = (arr, current, len) => {
40
+ let i = len - 1;
41
+ while (i > 0) {
42
+ const item = arr[i];
43
+ const pI = getParent(i, len);
44
+ const parent = arr[pI];
45
+ if (this.aIsUrgent(item, parent)) {
46
+ exchange(arr, i, pI);
47
+ i = pI;
48
+ } else {
49
+ break;
50
+ }
51
+ }
52
+ };
53
+ this.goDown = (arr, i) => {
54
+ const len = this.size();
55
+ const half = len >>> 1;
56
+ while (i < half) {
57
+ const lI = getLeft(i, len);
58
+ const rI = getRight(i, len);
59
+ let point = i;
60
+ if (lI != null && this.aIsUrgent(arr[lI], arr[point])) {
61
+ point = lI;
62
+ }
63
+ if (rI != null && this.aIsUrgent(arr[rI], arr[point])) {
64
+ point = rI;
65
+ }
66
+ if (point === i) {
67
+ break;
68
+ }
69
+ exchange(arr, i, point);
70
+ i = point;
71
+ }
72
+ };
73
+ }
74
+ // 添加一个元素
75
+ _add(current) {
76
+ this.arr.push(current);
77
+ const len = this.size();
78
+ if (len === 1) {
79
+ return;
13
80
  }
14
- };
15
- }
16
- function Queue_$$$_push(it) {
17
- this.len++;
18
- const {
19
- _last: last
20
- } = this;
21
- const item = {
22
- v: it
23
- };
24
- if (!last) {
25
- this._first = this._last = item;
26
- return;
81
+ this.goUp(this.arr, current, len);
27
82
  }
28
- item.prev = this._last;
29
- last.next = item;
30
- this._last = item;
31
- }
32
- function Queue_$$$_shift() {
33
- const {
34
- _first: first
35
- } = this;
36
- if (!first) return undefined;
37
- this.len--;
38
- const {
39
- next
40
- } = first;
41
- first.next = undefined;
42
- if (next) {
43
- next.prev = undefined;
44
- } else {
45
- this._last = undefined;
83
+ add(...items) {
84
+ items.forEach((it) => this._add(it));
85
+ }
86
+ // 去除头元素并返回
87
+ poll() {
88
+ const { arr } = this;
89
+ const len = this.size();
90
+ if (len <= 2) {
91
+ return arr.shift();
92
+ }
93
+ const last = arr.pop();
94
+ const first = arr[0];
95
+ arr[0] = last;
96
+ this.goDown(this.arr, 0);
97
+ return first;
98
+ }
99
+ // 取得头元素
100
+ peek() {
101
+ return this.arr[0];
102
+ }
103
+ // 取得元素数量
104
+ size() {
105
+ return this.arr.length;
106
+ }
107
+ logTree() {
108
+ const { arr } = this;
109
+ let i = 0;
110
+ let j = 1;
111
+ let level = 0;
112
+ const matrix = [];
113
+ do {
114
+ matrix.push(arr.slice(i, j));
115
+ i = i * 2 + 1;
116
+ j = i + Math.pow(2, level) + 1;
117
+ level++;
118
+ } while (i < arr.length);
119
+ const last = Math.pow(2, matrix.length - 1);
120
+ const arrStr = JSON.stringify(last);
121
+ const halfLen = arrStr.length >>> 1;
122
+ matrix.forEach((it) => {
123
+ const str = JSON.stringify(it);
124
+ const halfIt = str.length >>> 1;
125
+ console.log(str.padStart(halfLen + halfIt, " "));
126
+ });
127
+ console.log("\n");
46
128
  }
47
- this._first = next;
48
- return first.v;
49
- }
50
- function SortMap() {
51
- return {
52
- data: {},
53
- clear: SortMap_$$$_clear,
54
- add: SortMap_$$$_add
55
- };
56
- }
57
- // const queue = new Queue([1,2,3,4]);
58
- // queue.shift()
59
- // queue.pop()
60
- // // @ts-ignore
61
- // queue.unshift('a')
62
- // // @ts-ignore
63
- // queue.push('b')
64
- // queue.shift()
65
- // queue.pop()
66
- // queue.shift()
67
- // queue.pop()
68
- // queue.shift()
69
- // queue.pop()
70
- // queue.push(10)
71
- // queue.array();
72
- function SortMap_$$$_clear() {
73
- this.data = {};
74
129
  }
75
- function SortMap_$$$_add(key, value) {
76
- const {
77
- data
78
- } = this;
79
- let list = data[key];
80
- if (!list) {
81
- list = [];
82
- data[key] = list;
130
+
131
+ class TaskQueue {
132
+ constructor(callbackAble, aIsUrgent) {
133
+ this.callbackAble = callbackAble;
134
+ this.aIsUrgent = aIsUrgent;
135
+ this.isScheduling = false;
136
+ }
137
+ static create({ callbackAble, aIsUrgent }) {
138
+ const queue = new TaskQueue(callbackAble, aIsUrgent);
139
+ queue.taskQueue = new PriorityQueue(aIsUrgent);
140
+ return queue;
141
+ }
142
+ pushTask(task) {
143
+ const { taskQueue, isScheduling } = this;
144
+ taskQueue._add(task);
145
+ if (!isScheduling) {
146
+ this.callbackAble(this.scheduleTask.bind(this));
147
+ this.isScheduling = true;
148
+ }
149
+ }
150
+ scheduleTask() {
151
+ const { taskQueue } = this;
152
+ const fn = taskQueue.peek();
153
+ if (!fn) return this.isScheduling = false;
154
+ const hasRemain = fn();
155
+ if (hasRemain) {
156
+ this.callbackAble(this.scheduleTask.bind(this));
157
+ return;
158
+ }
159
+ taskQueue.poll();
160
+ evt.emit("one", fn);
161
+ if (taskQueue.size() === 0) {
162
+ evt.emit("done", fn);
163
+ return this.isScheduling = false;
164
+ }
165
+ this.callbackAble(this.scheduleTask.bind(this));
83
166
  }
84
- list.push(value);
85
167
  }
86
168
 
87
- const G = {
88
- /** 原子 signal 更新次数 */
89
- version: 0,
90
- id: 0,
91
- /** scope 销毁任务序号 */
92
- scopeDisposeI: 0
169
+ let channel = globalThis.MessageChannel ? new MessageChannel() : null;
170
+ if (globalThis.MessageChannel) {
171
+ channel = new MessageChannel();
172
+ }
173
+ let msgId = 0;
174
+ const macro = (fn) => {
175
+ if (!channel) {
176
+ setTimeout(fn);
177
+ }
178
+ const memoId = msgId;
179
+ function onMessage(e) {
180
+ if (memoId === e.data) {
181
+ fn();
182
+ channel.port2.removeEventListener("message", onMessage);
183
+ }
184
+ }
185
+ channel.port2.addEventListener("message", onMessage);
186
+ channel.port1.postMessage(msgId++);
187
+ };
188
+ const p = Promise.resolve();
189
+ const micro = (cb) => {
190
+ p.then(cb);
93
191
  };
94
- const dirtyLeafs = SortMap();
95
- var State;
96
- (function (State) {
97
- State[State["Clean"] = 0] = "Clean";
98
- /** 仅用于 scope 节点是否 abort */
99
- State[State["ScopeAbort"] = 32] = "ScopeAbort";
100
- State[State["OutLink"] = 16] = "OutLink";
101
- State[State["Unknown"] = 8] = "Unknown";
102
- State[State["Dirty"] = 4] = "Dirty";
103
- State[State["Check"] = 2] = "Check";
104
- State[State["ScopeReady"] = 1] = "ScopeReady";
105
- })(State || (State = {}));
106
- const DirtyState = State.Unknown | State.Dirty;
107
192
 
108
- var Scheduler;
109
- (function (Scheduler) {
110
- Scheduler["Sync"] = "__Sync_";
111
- Scheduler["Layout"] = "__Layout_";
112
- Scheduler["Micro"] = "__Micro_";
113
- Scheduler["Macro"] = "__Macro_";
114
- })(Scheduler || (Scheduler = {}));
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 || {});
115
200
  const _scheduler = {
116
- [Scheduler.Sync]: defaultScheduler,
117
- [Scheduler.Micro]: microScheduler,
118
- [Scheduler.Macro]: macroScheduler,
119
- [Scheduler.Layout]: schedulerLayout
201
+ ["__Sync_" /* Sync */]: defaultScheduler,
202
+ ["__Micro_" /* Micro */]: microScheduler,
203
+ ["__Macro_" /* Macro */]: macroScheduler,
204
+ ["__Layout_" /* Layout */]: layoutScheduler
120
205
  };
121
206
  const scheduler = (key, value) => _scheduler[key] = value;
122
207
  function defaultScheduler(effects) {
@@ -124,70 +209,57 @@ function defaultScheduler(effects) {
124
209
  effect.runIfDirty();
125
210
  }
126
211
  }
127
- const p = Promise.resolve();
128
- let hasMicroTask = false;
212
+ let microSTaskQueue;
213
+ let macroSTaskQueue;
214
+ let layoutSTaskQueue;
129
215
  function microScheduler(effects) {
130
- if (hasMicroTask) return;
131
- p.then(() => {
132
- defaultScheduler(effects);
133
- hasMicroTask = false;
134
- });
135
- hasMicroTask = true;
136
- }
137
- let channel, macroQueue;
138
- if (globalThis.MessageChannel) {
139
- channel = new MessageChannel();
140
- macroQueue = Queue();
141
- channel.port2.onmessage = () => {
142
- while (macroQueue.first) {
143
- macroQueue.shift()();
144
- }
145
- };
216
+ microSTaskQueue = microSTaskQueue || TaskQueue.create({ callbackAble: micro, aIsUrgent: (a, b) => a.time < b.time });
217
+ microSTaskQueue.pushTask(defaultScheduler.bind(null, effects));
146
218
  }
147
219
  function macroScheduler(effects) {
148
- if (channel) {
149
- macroQueue.push(() => defaultScheduler(effects));
150
- channel.port1.postMessage('');
151
- }
152
- setTimeout(() => {
153
- defaultScheduler(effects);
154
- });
220
+ macroSTaskQueue = macroSTaskQueue || TaskQueue.create({ callbackAble: macro, aIsUrgent: (a, b) => a.time < b.time });
221
+ macroSTaskQueue.pushTask(defaultScheduler.bind(null, effects));
155
222
  }
156
- function schedulerLayout(effects) {
157
- requestAnimationFrame(() => {
158
- defaultScheduler(effects);
159
- });
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));
160
226
  }
161
227
 
228
+ var __defProp$1 = Object.defineProperty;
229
+ var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
230
+ var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
231
+ var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
232
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
233
+ var __spreadValues$1 = (a, b) => {
234
+ for (var prop in b || (b = {}))
235
+ if (__hasOwnProp$2.call(b, prop))
236
+ __defNormalProp$1(a, prop, b[prop]);
237
+ if (__getOwnPropSymbols$2)
238
+ for (var prop of __getOwnPropSymbols$2(b)) {
239
+ if (__propIsEnum$2.call(b, prop))
240
+ __defNormalProp$1(a, prop, b[prop]);
241
+ }
242
+ return a;
243
+ };
162
244
  const DefaultDFSOpt = {
163
245
  isUp: false,
164
- begin: undefined,
165
- complete: undefined,
246
+ begin: null,
247
+ complete: null,
166
248
  breakStack: [],
167
- breakLine: undefined,
168
- breakNode: undefined
249
+ breakLine: null,
250
+ breakNode: null
169
251
  };
170
252
  function dfs(root, opt = {}) {
171
- const {
172
- isUp,
173
- begin,
174
- complete,
175
- breakStack: lineStack,
176
- breakLine
177
- } = {
178
- ...DefaultDFSOpt,
179
- ...opt
180
- };
253
+ const { isUp, begin, complete, breakStack: lineStack, breakLine } = __spreadValues$1(__spreadValues$1({}, DefaultDFSOpt), opt);
181
254
  let node = opt.breakNode || root;
182
255
  let line = breakLine;
183
- const listKey = isUp ? 'recStart' : 'emitStart';
184
- const nodeKey = isUp ? 'upstream' : 'downstream';
185
- // 向上意味着要找所有节点的入度
186
- const nextLineKey = isUp ? 'nextRecLine' : 'nextEmitLine';
187
- const reverseNodeKey = isUp ? 'downstream' : 'upstream';
256
+ const listKey = isUp ? "recStart" : "emitStart";
257
+ const nodeKey = isUp ? "upstream" : "downstream";
258
+ const nextLineKey = isUp ? "nextRecLine" : "nextEmitLine";
259
+ const reverseNodeKey = isUp ? "downstream" : "upstream";
188
260
  while (1) {
189
- let notGoDeep = begin === null || begin === void 0 ? void 0 : begin({
190
- node: node,
261
+ let notGoDeep = begin == null ? void 0 : begin({
262
+ node,
191
263
  lineFromUp: line,
192
264
  walkedLine: lineStack
193
265
  });
@@ -199,622 +271,303 @@ function dfs(root, opt = {}) {
199
271
  continue;
200
272
  }
201
273
  while (1) {
202
- const noGoSibling = complete === null || complete === void 0 ? void 0 : complete({
203
- node: node,
274
+ const noGoSibling = complete == null ? void 0 : complete({
275
+ node,
204
276
  lineToDeep: line,
205
277
  walkedLine: lineStack,
206
278
  notGoDeep
207
279
  });
208
- // 只对当前不下钻的节点生效
209
- // notGoDeep = false;
210
280
  line = lineStack.pop();
211
- // 递归出口,回到起点
212
281
  if (node === root) {
213
282
  return;
214
283
  }
215
284
  notGoDeep = false;
216
285
  const nextLine = line[nextLineKey];
217
- // 有兄弟节点, 进入外循环,向下遍历兄弟节点
218
286
  if (!noGoSibling && nextLine) {
219
- // 外层循环后会把 sibling line 入栈,这里不需要处理
220
287
  line = nextLine;
221
288
  node = nextLine[nodeKey];
222
289
  break;
223
290
  }
224
- // 没有兄弟节点就上浮
225
291
  node = line[reverseNodeKey];
226
292
  }
227
293
  }
228
294
  }
229
295
 
230
- function Line_$$$_link(v1, v2) {
231
- let {
232
- emitEnd
233
- } = v1,
234
- {
235
- recEnd,
236
- recStart
237
- } = v2,
238
- noRecEnd = !recEnd,
239
- /** 模拟头节点 */
240
- head = {
241
- nextRecLine: recStart
242
- },
243
- line;
244
- recEnd = recEnd || head;
245
- const {
246
- nextRecLine
247
- } = recEnd || {};
248
- // 没有下一个收到的线
249
- if (!nextRecLine) {
250
- line = Line();
251
- // 内部会处理空链表的情况,即同步头部
252
- Line.emit_line(v1, line);
253
- Line.rec_line(v2, line);
254
- emitEnd && Line.line_line_emit(emitEnd, line);
255
- !noRecEnd && Line.line_line_rec(recEnd, line);
256
- }
257
- // 复用
258
- else if (nextRecLine.upstream === v1) {
259
- v2.recEnd = nextRecLine;
260
- // TODO: link 版本标记
261
- }
262
- // 插入(这么做): v1 和 下一个 入度(订阅)节点不同
263
- // TODO: v2上次真依赖了 v1 只是没检查出来,需要删除原依赖
264
- else {
265
- line = Line();
266
- Line.emit_line(v1, line);
267
- Line.rec_line(v2, line);
268
- emitEnd && Line.line_line_emit(emitEnd, line);
269
- Line.insert_line_rec(recEnd, nextRecLine, line);
296
+ class Line {
297
+ constructor() {
298
+ /** 上游顶点 */
299
+ this.upstream = null;
300
+ /** 上游节点 发出的上一条线 */
301
+ this.prevEmitLine = null;
302
+ /** 上游节点 发出的下一条线 */
303
+ this.nextEmitLine = null;
304
+ /** 下游顶点 */
305
+ this.downstream = null;
306
+ /** 下游节点 接收的上一条线 */
307
+ this.prevRecLine = null;
308
+ /** 下游节点 接收的下一条线 */
309
+ this.nextRecLine = null;
310
+ /** 表示 scope 当前存在的 外部 link */
311
+ this.prevOutLink = null;
312
+ this.nextOutLink = null;
313
+ }
314
+ static link(v1, v2) {
315
+ let { emitEnd } = v1, { recEnd, recStart } = v2, noRecEnd = !recEnd, head = { nextRecLine: recStart }, line;
316
+ recEnd = recEnd || head;
317
+ const { nextRecLine } = recEnd || {};
318
+ if (!nextRecLine) {
319
+ line = new Line();
320
+ Line.emit_line(v1, line);
321
+ Line.rec_line(v2, line);
322
+ emitEnd && Line.line_line_emit(emitEnd, line);
323
+ !noRecEnd && Line.line_line_rec(recEnd, line);
324
+ } else if (nextRecLine.upstream === v1) {
325
+ v2.recEnd = nextRecLine;
326
+ } else {
327
+ line = new Line();
328
+ Line.emit_line(v1, line);
329
+ Line.rec_line(v2, line);
330
+ emitEnd && Line.line_line_emit(emitEnd, line);
331
+ Line.insert_line_rec(recEnd, nextRecLine, line);
332
+ }
333
+ for (const key in head) {
334
+ head[key] = null;
335
+ }
336
+ if (line && v2.scope && v1.scope !== v2.scope && !(v1.state & State.IsScope)) {
337
+ const first = v2.scope.outLink;
338
+ if (!first) {
339
+ v2.scope.outLink = line;
340
+ } else {
341
+ first.prevOutLink = line;
342
+ line.nextOutLink = first;
343
+ v2.scope.outLink = line;
344
+ }
345
+ }
270
346
  }
271
- // 消除 head
272
- for (const key in head) {
273
- head[key] = undefined;
347
+ static unlink(line) {
348
+ let { prevEmitLine, nextEmitLine, prevRecLine, nextRecLine, upstream, downstream, nextOutLink, prevOutLink } = line;
349
+ line.prevEmitLine = null;
350
+ line.nextEmitLine = null;
351
+ line.prevRecLine = null;
352
+ line.nextRecLine = null;
353
+ line.upstream = null;
354
+ line.downstream = null;
355
+ line.prevOutLink = null;
356
+ line.nextOutLink = null;
357
+ const downNode = downstream;
358
+ if (prevOutLink) {
359
+ prevOutLink.nextOutLink = nextOutLink;
360
+ }
361
+ if (nextOutLink) {
362
+ nextOutLink.prevOutLink = prevOutLink;
363
+ }
364
+ if (downNode.scope && downNode.scope.outLink === line) {
365
+ downNode.scope.outLink = nextOutLink;
366
+ }
367
+ if (prevEmitLine) {
368
+ prevEmitLine.nextEmitLine = nextEmitLine;
369
+ } else {
370
+ upstream.emitStart = nextEmitLine;
371
+ }
372
+ if (nextEmitLine) {
373
+ nextEmitLine.prevEmitLine = prevEmitLine;
374
+ } else {
375
+ upstream.emitEnd = prevEmitLine;
376
+ }
377
+ if (prevRecLine) {
378
+ prevRecLine.nextRecLine = nextRecLine;
379
+ } else {
380
+ downstream.recStart = nextRecLine;
381
+ }
382
+ if (nextRecLine) {
383
+ nextRecLine.prevRecLine = prevRecLine;
384
+ } else {
385
+ downstream.recEnd = prevRecLine;
386
+ }
274
387
  }
275
- }
276
- Line.link = Line_$$$_link;
277
- function Line_$$$_unlink(line) {
278
- let {
279
- prevEmitLine,
280
- nextEmitLine,
281
- prevRecLine,
282
- nextRecLine,
283
- upstream,
284
- downstream
285
- } = line;
286
- line.prevEmitLine = undefined;
287
- line.nextEmitLine = undefined;
288
- line.prevRecLine = undefined;
289
- line.nextRecLine = undefined;
290
- line.upstream = undefined;
291
- line.downstream = undefined;
292
- /** 上游节点发出的线 前一条 关联 后一条 */
293
- if (prevEmitLine) {
294
- prevEmitLine.nextEmitLine = nextEmitLine;
295
- } else {
296
- // 删除的是首个节点
297
- upstream.emitStart = nextEmitLine;
388
+ static unlinkRec(line) {
389
+ let toDel = line;
390
+ while (toDel) {
391
+ const memoNext = toDel.nextRecLine;
392
+ Line.unlink(toDel);
393
+ toDel = memoNext;
394
+ }
298
395
  }
299
- if (nextEmitLine) {
300
- nextEmitLine.prevEmitLine = prevEmitLine;
301
- } else {
302
- // 删除尾节点
303
- upstream.emitEnd = prevEmitLine;
396
+ static unlinkEmit(line) {
397
+ let toDel = line;
398
+ while (toDel) {
399
+ const memoNext = toDel.nextEmitLine;
400
+ Line.unlink(toDel);
401
+ toDel = memoNext;
402
+ }
304
403
  }
305
- /** 下游节点接收的线,我们从 recEnd 开始删除的,
306
- * 接收信息,不需要设置 recEnd
307
- * 因为 recStart ~ recEnd 是经过上级 get 确认的有用依赖
308
- * */
309
- if (prevRecLine) {
310
- prevRecLine.nextRecLine = nextRecLine;
311
- } else {
312
- // 删除的是首个节点,大概率不可能从有依赖 变成无依赖
313
- downstream.recStart = nextRecLine;
404
+ /** 上游节点 link */
405
+ static emit_line(upstream, line) {
406
+ if (!upstream.emitStart) {
407
+ upstream.emitStart = line;
408
+ }
409
+ upstream.emitEnd = line;
410
+ line.upstream = upstream;
314
411
  }
315
- if (nextRecLine) {
316
- nextRecLine.prevRecLine = prevRecLine;
317
- } else {
318
- // 删除尾节点
319
- downstream.recEnd = prevRecLine;
412
+ /** 下游节点 连 link */
413
+ static rec_line(downstream, line) {
414
+ if (!downstream.recStart) {
415
+ downstream.recStart = line;
416
+ }
417
+ downstream.recEnd = line;
418
+ line.downstream = downstream;
419
+ }
420
+ /** 同一节点发出的 两个条线 相连 */
421
+ static line_line_emit(l1, l2) {
422
+ if (!l1 || !l2) return;
423
+ l1.nextEmitLine = l2;
424
+ l2.prevEmitLine = l1;
425
+ }
426
+ /** 同一节点接收的 两个条线 相连 */
427
+ static line_line_rec(l1, l2) {
428
+ if (!l1 || !l2) return;
429
+ l1.nextRecLine = l2;
430
+ l2.prevRecLine = l1;
431
+ }
432
+ static insert_line_emit(l1, l2, ins) {
433
+ l1.nextEmitLine = ins;
434
+ ins.prevEmitLine = l1;
435
+ l2.prevEmitLine = ins;
436
+ ins.nextEmitLine = l2;
437
+ }
438
+ static insert_line_rec(l1, l2, ins) {
439
+ l1.nextRecLine = ins;
440
+ ins.prevRecLine = l1;
441
+ l2.prevRecLine = ins;
442
+ ins.nextRecLine = l2;
320
443
  }
321
444
  }
322
- Line.unlink = Line_$$$_unlink;
323
- function Line_$$$_unlinkRec(line) {
324
- // 作为下游,执行完 get 上游节点已经完成了依赖更新,把 recEnd 后的依赖删除即可
445
+
446
+ function unlinkRecWithScope(line) {
325
447
  let toDel = line;
326
448
  while (toDel) {
327
449
  const memoNext = toDel.nextRecLine;
328
- Line.unlink(toDel);
329
- toDel = memoNext;
330
- }
331
- }
332
- Line.unlinkRec = Line_$$$_unlinkRec;
333
- function Line_$$$_unlinkEmit(line) {
334
- // 作为下游,执行完 get 上游节点已经完成了依赖更新,把 recEnd 后的依赖删除即可
335
- let toDel = line;
336
- while (toDel) {
337
- const memoNext = toDel.nextEmitLine;
338
- Line.unlink(toDel);
450
+ const upstream = toDel.upstream;
451
+ if (upstream.state & State.IsScope) {
452
+ dispose.call(upstream);
453
+ } else {
454
+ unlinkSingleLine(toDel);
455
+ }
339
456
  toDel = memoNext;
340
457
  }
341
458
  }
342
- Line.unlinkEmit = Line_$$$_unlinkEmit;
343
- function Line_$$$_emit_line(upstream, line) {
344
- if (!upstream.emitStart) {
345
- upstream.emitStart = line;
346
- }
347
- upstream.emitEnd = line;
348
- line.upstream = upstream;
349
- }
350
- Line.emit_line = Line_$$$_emit_line;
351
- function Line_$$$_rec_line(downstream, line) {
352
- if (!downstream.recStart) {
353
- downstream.recStart = line;
459
+ function unlinkSingleLine(line) {
460
+ const upstream = line.upstream;
461
+ if (upstream.emitStart === upstream.emitEnd) {
462
+ unlinkSingleRefedNode(upstream);
463
+ } else {
464
+ Line.unlink(line);
354
465
  }
355
- downstream.recEnd = line;
356
- line.downstream = downstream;
357
466
  }
358
- Line.rec_line = Line_$$$_rec_line;
359
- function Line_$$$_line_line_emit(l1, l2) {
360
- if (!l1 || !l2) return;
361
- l1.nextEmitLine = l2;
362
- l2.prevEmitLine = l1;
363
- }
364
- Line.line_line_emit = Line_$$$_line_line_emit;
365
- function Line_$$$_line_line_rec(l1, l2) {
366
- if (!l1 || !l2) return;
367
- l1.nextRecLine = l2;
368
- l2.prevRecLine = l1;
369
- }
370
- Line.line_line_rec = Line_$$$_line_line_rec;
371
- function Line_$$$_insert_line_emit(l1, l2, ins) {
372
- l1.nextEmitLine = ins;
373
- ins.prevEmitLine = l1;
374
- l2.prevEmitLine = ins;
375
- ins.nextEmitLine = l2;
376
- }
377
- Line.insert_line_emit = Line_$$$_insert_line_emit;
378
- function Line_$$$_insert_line_rec(l1, l2, ins) {
379
- l1.nextRecLine = ins;
380
- ins.prevRecLine = l1;
381
- l2.prevRecLine = ins;
382
- ins.nextRecLine = l2;
383
- }
384
- Line.insert_line_rec = Line_$$$_insert_line_rec;
385
- function Line() {
386
- return {
387
- upstream: null,
388
- prevEmitLine: null,
389
- nextEmitLine: null,
390
- downstream: null,
391
- prevRecLine: null,
392
- nextRecLine: null
393
- };
394
- }
395
-
396
- /**
397
- * 这是一个优先队列 (满足子节点总是比父节点大)
398
- * 1
399
- *
400
- * 10 20
401
- *
402
- * 15 30 25 30
403
- *
404
- * 17
405
- * 现在插入 7 , 会按广度优先的顺序插入在数组尾部
406
- * 1
407
- *
408
- * 10 20
409
- *
410
- * 15 30 25 30
411
- *
412
- * 17 7
413
- * 接着我们只需要将 7 逐层与上门的父节点比较, 7 较小则两者交互,一直让 7 上浮到适合的位置
414
- *
415
- * 0
416
- *
417
- * 1 2 2^0 得到第二层第一个索引
418
- *
419
- * 3 4 5 6 2^0 + 2^1 。。。 + 2^n + x = y
420
- *
421
- * 7 8
422
- * 上浮后我们得到以上的树
423
- */
424
- // 父子节点的关系
425
- // 计算一个节点的 index 公式 ① 2^0 + 2^1 。。。 + 2^n + y = x 已知
426
- // 节点的左子节点 index ② 2^0 + 2^1 。。。 + 2^n + 2^(n+1) + z = res 求 res
427
- // ② - ① 得到 2^(n+1) + (z-y) = res - x
428
- // 2^(n+1) + (z-y) + x = res
429
- // 而 z 和 y 的关系是,③ z = 2y
430
- const leakI = (y, max) => y < 0 || y >= max ? null : y;
431
- const getLeft = (x, max) => leakI(x * 2 + 1, max);
432
- const getRight = (x, max) => leakI(x * 2 + 2, max);
433
- const getParent = (x, max) => leakI(x - 1 >>> 1, max);
434
- const exchange = (arr, i, j) => [arr[i], arr[j]] = [arr[j], arr[i]];
435
- function PriorityQueue(aIsUrgent) {
436
- return {
437
- aIsUrgent: aIsUrgent,
438
- arr: [],
439
- goUp: (arr, current, len) => {
440
- let i = len - 1;
441
- while (i > 0) {
442
- const item = arr[i];
443
- const pI = getParent(i, len);
444
- const parent = arr[pI];
445
- if (this.aIsUrgent(item, parent)) {
446
- // console.log(`交换 parent:${parent} -> child:${item} `);
447
- exchange(arr, i, pI);
448
- // this.logTree();
449
- i = pI;
450
- } else {
451
- // console.log(`parent:${parent} child:${item} 不需要交换 \n`);
452
- break;
453
- }
467
+ function unlinkSingleRefedNode(delRoot) {
468
+ let toUnlink;
469
+ dfs(delRoot, {
470
+ isUp: true,
471
+ begin: ({ node }) => {
472
+ doUnlink(toUnlink);
473
+ toUnlink = null;
474
+ if (node.emitStart !== node.emitEnd) {
475
+ return true;
454
476
  }
455
477
  },
456
- goDown: (arr, i) => {
457
- const len = this.size();
458
- const half = len >>> 1;
459
- while (i < half) {
460
- const lI = getLeft(i, len);
461
- const rI = getRight(i, len);
462
- let point = i;
463
- if (lI != null && this.aIsUrgent(arr[lI], arr[point])) {
464
- point = lI;
465
- }
466
- if (rI != null && this.aIsUrgent(arr[rI], arr[point])) {
467
- point = rI;
468
- }
469
- if (point === i) {
470
- break;
471
- }
472
- // console.log(`交换 parent:${arr[i]} -> child:${arr[point]} `);
473
- exchange(arr, i, point);
474
- // this.logTree();
475
- i = point;
478
+ complete: ({ node, notGoDeep }) => {
479
+ doUnlink(toUnlink);
480
+ toUnlink = null;
481
+ const isSingleRefed = !notGoDeep;
482
+ if (isSingleRefed) {
483
+ toUnlink = node.emitStart;
476
484
  }
477
- },
478
- _add: PriorityQueue_$$$__add,
479
- add: PriorityQueue_$$$_add,
480
- poll: PriorityQueue_$$$_poll,
481
- peek: PriorityQueue_$$$_peek,
482
- size: PriorityQueue_$$$_size,
483
- logTree: PriorityQueue_$$$_logTree
484
- };
485
- }
486
- // case 1
487
- // const pq = new PriorityQueue((a, b) => a - b)
488
- // pq.add(5)
489
- // pq.add(3)
490
- // pq.add(1)
491
- // pq.add(4)
492
- // pq.add(2)
493
- // const result = []
494
- // while (pq.size() > 0) {
495
- // result.push(pq.poll())
496
- // }
497
- // console.log(result);
498
- // [1,2,3,4,5]
499
- // case 2
500
- // const pq = new PriorityQueue((a, b) => b - a)
501
- // pq.add(1)
502
- // pq.add(3)
503
- // pq.add(4)
504
- // pq.add(5)
505
- // pq.add(2)
506
- // const result = []
507
- // while (pq.size() > 0) {
508
- // result.push(pq.poll())
509
- // }
510
- // console.log(result);
511
- // [5,4,3,2,1]
512
- function PriorityQueue_$$$__add(current) {
513
- // console.log(`加入 ${current}`);
514
- this.arr.push(current);
515
- const len = this.size();
516
- // this.logTree();
517
- if (len === 1) {
518
- return;
519
- }
520
- this.goUp(this.arr, current, len);
521
- }
522
- function PriorityQueue_$$$_add(...items) {
523
- items.forEach(it => this._add(it));
524
- }
525
- function PriorityQueue_$$$_poll() {
526
- const {
527
- arr
528
- } = this;
529
- // console.log(`弹出 ${arr[0]} 把 ${arr[arr.length - 1]} 放置到队头 `);
530
- const len = this.size();
531
- if (len <= 2) {
532
- return arr.shift();
533
- }
534
- const last = arr.pop();
535
- const first = arr[0];
536
- arr[0] = last;
537
- // this.logTree();
538
- this.goDown(this.arr, 0);
539
- return first;
540
- }
541
- function PriorityQueue_$$$_peek() {
542
- return this.arr[0];
543
- }
544
- function PriorityQueue_$$$_size() {
545
- return this.arr.length;
546
- }
547
- function PriorityQueue_$$$_logTree() {
548
- const {
549
- arr
550
- } = this;
551
- let i = 0;
552
- let j = 1;
553
- let level = 0;
554
- const matrix = [];
555
- do {
556
- matrix.push(arr.slice(i, j));
557
- i = i * 2 + 1;
558
- j = i + Math.pow(2, level) + 1;
559
- level++;
560
- } while (i < arr.length);
561
- const last = Math.pow(2, matrix.length - 1);
562
- const arrStr = JSON.stringify(last);
563
- const halfLen = arrStr.length >>> 1;
564
- matrix.forEach(it => {
565
- const str = JSON.stringify(it);
566
- const halfIt = str.length >>> 1;
567
- console.log(str.padStart(halfLen + halfIt, ' '));
485
+ }
568
486
  });
569
- console.log('\n');
570
- }
571
-
572
- function TaskQueue_$$$_create({
573
- callbackAble,
574
- aIsUrgent
575
- }) {
576
- const queue = TaskQueue(callbackAble, aIsUrgent);
577
- queue.taskQueue = PriorityQueue(aIsUrgent);
578
- return queue;
487
+ doUnlink(toUnlink);
579
488
  }
580
- TaskQueue.create = TaskQueue_$$$_create;
581
- function TaskQueue(callbackAble, aIsUrgent) {
582
- return {
583
- callbackAble: callbackAble,
584
- aIsUrgent: aIsUrgent,
585
- isScheduling: false,
586
- pushTask: TaskQueue_$$$_pushTask,
587
- scheduleTask: TaskQueue_$$$_scheduleTask
588
- };
589
- }
590
- function TaskQueue_$$$_pushTask(task) {
591
- const {
592
- taskQueue,
593
- isScheduling
594
- } = this;
595
- taskQueue._add(task);
596
- if (!isScheduling) {
597
- this.callbackAble(this.scheduleTask.bind(this));
598
- this.isScheduling = true;
599
- }
600
- }
601
- function TaskQueue_$$$_scheduleTask() {
602
- const {
603
- taskQueue
604
- } = this;
605
- // console.log('调度 dispose');
606
- const fn = taskQueue.peek();
607
- if (!fn) return this.isScheduling = false;
608
- const hasRemain = fn();
609
- // 未完成
610
- if (hasRemain) {
611
- this.callbackAble(this.scheduleTask.bind(this));
489
+ function doUnlink(line) {
490
+ if (!line) {
612
491
  return;
613
492
  }
614
- // 完成
615
- taskQueue.poll();
616
- if (taskQueue.size() === 0) return this.isScheduling = false;
617
- // 任务列表中还有任务
618
- this.callbackAble(this.scheduleTask.bind(this));
619
- }
620
-
621
- const ide = globalThis.requestIdleCallback || (globalThis.requestAnimationFrame ? fn => globalThis.requestAnimationFrame(() => {
622
- setTimeout(() => {
623
- fn();
624
- });
625
- }) : globalThis.setTimeout);
626
- const now = () => {
627
- const timer = globalThis.performance || globalThis.Date;
628
- return timer.now();
629
- };
630
-
631
- // export class IdeScheduler {
632
- // constructor() {}
633
- // isScheduling = false;
634
- // taskQueue = new Queue<Function>();
635
- // pushTask(task: Function) {
636
- // const { taskQueue, isScheduling } = this;
637
- // taskQueue.push(task);
638
- // if (!isScheduling) {
639
- // ide(this.scheduleTask.bind(this));
640
- // this.isScheduling = true;
641
- // }
642
- // }
643
- // scheduleTask() {
644
- // const { taskQueue } = this;
645
- // // console.log('调度 dispose');
646
- // const fn = taskQueue.first;
647
- // if (!fn) return (this.isScheduling = false);
648
- // const hasRemain = fn();
649
- // // 未完成
650
- // if (hasRemain) {
651
- // ide(this.scheduleTask.bind(this));
652
- // return;
653
- // }
654
- // // 完成
655
- // taskQueue.shift();
656
- // if (taskQueue.len === 0) return (this.isScheduling = false);
657
- // // 任务列表中还有任务
658
- // ide(this.scheduleTask.bind(this));
659
- // }
660
- // }
661
- /** scope 捕获,引用外部 signal 孤岛 */
662
- const unTrackIsland = signal => {
663
- // 原来是孤岛,且被 scope 管理的要恢复
664
- if (signal.emitStart && signal.emitStart.downstream === signal.scope) {
665
- Line.unlink(signal.emitStart);
666
- }
667
- };
668
- /** scope 释放,被重新连接的孤岛 */
669
- const trackIsland = signal => {
670
- const line = Line();
671
- // 上游节点处于孤岛状态,切有引用外部信号,需要被 scope 管理来删除外部依赖
672
- if (!signal.emitStart && signal.state & State.OutLink) {
673
- const {
674
- recEnd
675
- } = signal.scope;
676
- Line.emit_line(signal, line);
677
- Line.rec_line(signal.scope, line);
678
- Line.line_line_rec(recEnd, line);
679
- }
680
- };
681
- const markOutLink = (signal, downstream) => {
682
- // 上游是外部节点,或者上游引用了外部节点的, 做传播
683
- if (signal.scope !== downstream.scope || signal.state & State.OutLink) {
684
- downstream.state |= State.OutLink;
685
- }
686
- // else {
687
- // downstream.state &= ~State.OutLink;
688
- // }
689
- };
690
- const BreakErr = '_ERR_BREAK_';
691
- let remain = {
692
- stack: null,
693
- node: null,
694
- line: null
695
- };
696
- const ideScheduler = TaskQueue.create({
697
- callbackAble: ide,
698
- aIsUrgent(a, b) {
699
- return a.index < b.index;
700
- }
701
- });
702
- function handleOneTask(s, breakStack) {
703
- breakStack = remain.stack || breakStack;
704
- // 将 s 同步到 remainRoot
705
- let lineToRemove = null;
706
- const startTime = now();
707
- try {
708
- dfs(s, {
709
- breakStack,
710
- breakNode: remain.node,
711
- breakLine: remain.line,
712
- isUp: true,
713
- begin: ({
714
- walkedLine,
715
- node,
716
- lineFromUp
717
- }) => {
718
- if (lineToRemove) {
719
- Line.unlink(lineToRemove);
720
- lineToRemove = null;
721
- }
722
- if (now() - startTime > 5) {
723
- remain = {
724
- stack: walkedLine,
725
- node: node,
726
- line: lineFromUp
727
- };
728
- throw BreakErr;
729
- }
730
- if (!(node.state & State.OutLink)) {
731
- return true;
732
- }
733
- // 对于嵌套作用域不允许重复进入
734
- node.state &= ~State.OutLink;
735
- },
736
- complete: ({
737
- node,
738
- notGoDeep,
739
- walkedLine
740
- }) => {
741
- if (lineToRemove) {
742
- Line.unlink(lineToRemove);
743
- lineToRemove = null;
744
- }
745
- if (notGoDeep) {
746
- const last = walkedLine[walkedLine.length - 1];
747
- const downstream = last === null || last === void 0 ? void 0 : last.downstream;
748
- // 节点没被标记 OutLink 但是发现与下游节点的 scope 不一致,是需要解除 link 的位置
749
- if (downstream && downstream.scope !== node.scope) {
750
- lineToRemove = last;
751
- }
752
- }
753
- }
754
- });
755
- remain = {
756
- stack: null,
757
- node: null,
758
- line: null
759
- };
760
- } catch (error) {
761
- if (error === BreakErr) return true;
762
- remain = {
763
- stack: null,
764
- node: null,
765
- line: null
766
- };
767
- throw error;
768
- }
493
+ Line.unlink(line);
769
494
  }
770
- function unlinkRecWithScope(line) {
771
- // 作为下游,执行完 get 上游节点已经完成了依赖更新,把 recEnd 后的依赖删除即可
772
- let toDel = line;
495
+ function dispose() {
496
+ let toDel = this.recStart;
773
497
  while (toDel) {
774
498
  const memoNext = toDel.nextRecLine;
775
499
  const upstream = toDel.upstream;
776
- Line.unlink(toDel);
777
- // 删除完后看看是否要被 scope 管理
778
- trackIsland(upstream);
500
+ if (upstream.state & State.IsScope) {
501
+ dfs(upstream, {
502
+ isUp: true,
503
+ begin: ({ node }) => {
504
+ if (!(node.state & State.IsScope) || node.state & ScopeAbort) return true;
505
+ },
506
+ complete: ({ node: scope, notGoDeep }) => {
507
+ const shouldAbort = !notGoDeep;
508
+ if (shouldAbort) {
509
+ releaseScope(scope);
510
+ }
511
+ }
512
+ });
513
+ } else {
514
+ unlinkSingleLine(toDel);
515
+ }
779
516
  toDel = memoNext;
780
517
  }
518
+ releaseScope(this);
519
+ doUnlink(this.emitStart);
781
520
  }
782
-
783
- function Signal_$$$_create(nextValue, {
784
- customPull,
785
- isScope,
786
- ...rest
787
- }) {
788
- const s = Signal(nextValue, customPull);
789
- s.pull = s.customPull || s.DEFAULT_PULL;
790
- Object.assign(s, rest);
791
- if (isScope) {
792
- s.scope = s;
521
+ function releaseScope(scope) {
522
+ var _a;
523
+ let outLink = scope.outLink;
524
+ while (outLink) {
525
+ const memoNext = outLink.nextOutLink;
526
+ unlinkSingleLine(outLink);
527
+ outLink = memoNext;
793
528
  }
794
- return s;
529
+ scope.state |= State.ScopeAbort;
530
+ (_a = scope.clean) == null ? void 0 : _a.call(scope);
531
+ scope.clean = null;
532
+ }
533
+ function clean(cb) {
534
+ G.PullingSignal.clean = () => runWithPulling(cb, null);
795
535
  }
796
- Signal.create = Signal_$$$_create;
797
- const markDeep = signal => {
536
+ function runWithPulling(fn, signal) {
537
+ const prevPulling = G.PullingSignal;
538
+ G.PullingSignal = signal;
539
+ fn();
540
+ G.PullingSignal = prevPulling;
541
+ }
542
+
543
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
544
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
545
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
546
+ var __objRest = (source, exclude) => {
547
+ var target = {};
548
+ for (var prop in source)
549
+ if (__hasOwnProp$1.call(source, prop) && exclude.indexOf(prop) < 0)
550
+ target[prop] = source[prop];
551
+ if (source != null && __getOwnPropSymbols$1)
552
+ for (var prop of __getOwnPropSymbols$1(source)) {
553
+ if (exclude.indexOf(prop) < 0 && __propIsEnum$1.call(source, prop))
554
+ target[prop] = source[prop];
555
+ }
556
+ return target;
557
+ };
558
+ const markDeep = (signal) => {
798
559
  let level = 0;
799
560
  dfs(signal, {
800
561
  isUp: false,
801
- begin: ({
802
- node
803
- }) => {
804
- /**
805
- * 1. 当前节点在预检 应该跳过
806
- * 2. 当前节点 已标记
807
- * 3. 当前节点 已放弃
808
- */
809
- // console.log('markBegin', node.id);
810
- if (node.state & (State.Check | State.Unknown | State.Dirty) || node.isAbort()) {
562
+ begin: ({ node }) => {
563
+ if (node.state & (State.Check | State.Unknown | State.Dirty) || node.isDisabled()) {
811
564
  return true;
812
565
  }
813
566
  const isEffect = level > 0;
814
- const isLeaf = !node.emitStart || node.emitStart.downstream['scope'] === node.emitStart.downstream;
567
+ const isLeaf = !node.emitStart || node.emitStart.downstream === node.scope;
815
568
  if (isEffect) {
816
569
  node.state |= State.Unknown;
817
- } else {
570
+ } else if (!isLeaf) {
818
571
  node.state |= State.Dirty;
819
572
  }
820
573
  if (isLeaf && isEffect) {
@@ -830,283 +583,264 @@ const markDeep = signal => {
830
583
  }
831
584
  dirtyLeafs.clear();
832
585
  };
833
- function Signal(nextValue,
834
- /** 为什么是 shallow,因为 pullDeep 会把
835
- * 上游节点 get 执行完成,让其可以直接拿到缓存值
836
- */
837
- customPull) {
838
- return {
839
- nextValue: nextValue,
840
- customPull: customPull,
841
- version: -1,
842
- id: G.id++,
843
- state: State.Clean,
844
- scope: Signal.Pulling,
845
- recEnd: null,
846
- recStart: null,
847
- emitStart: null,
848
- emitEnd: null,
849
- scheduler: null,
850
- value: null,
851
- pull: null,
852
- DEFAULT_PULL: Signal_$$$_DEFAULT_PULL,
853
- pullRecurse: Signal_$$$_pullRecurse,
854
- pullDeep: Signal_$$$_pullDeep,
855
- get: Signal_$$$_get,
856
- markDownStreamsDirty: Signal_$$$_markDownStreamsDirty,
857
- set: Signal_$$$_set,
858
- run: Signal_$$$_run,
859
- runIfDirty: Signal_$$$_runIfDirty,
860
- isAbort: Signal_$$$_isAbort
861
- };
862
- }
863
- function Signal_$$$_DEFAULT_PULL() {
864
- return this.nextValue;
865
- }
866
- function Signal_$$$_pullRecurse(shouldLink = true) {
867
- var _a;
868
- let downstream = Signal.Pulling;
869
- if (shouldLink && downstream) {
870
- // 如果上游节点被 scope 管理了,解除管理
871
- unTrackIsland(this);
872
- Line.link(this, downstream);
586
+ const _Signal = class _Signal {
587
+ constructor(nextValue, customPull) {
588
+ this.nextValue = nextValue;
589
+ this.customPull = customPull;
590
+ this.version = -1;
591
+ this.id = G.id++;
592
+ this.state = State.Clean;
593
+ /** 当前节点创建时处于的 effect 就是 scope */
594
+ this.scope = G.PullingSignal;
595
+ this.recEnd = null;
596
+ this.recStart = null;
597
+ this.emitStart = null;
598
+ this.emitEnd = null;
599
+ this.scheduler = null;
600
+ this.value = null;
601
+ this.outLink = null;
602
+ this.pull = null;
603
+ /** 记录当前 effect 中 clean */
604
+ this.clean = null;
605
+ }
606
+ static create(nextValue, _a) {
607
+ var _b = _a, { customPull, isScope, immediate } = _b, rest = __objRest(_b, ["customPull", "isScope", "immediate"]);
608
+ const s = new _Signal(nextValue, customPull);
609
+ s.pull = s.customPull || s.DEFAULT_PULL;
610
+ Object.assign(s, rest);
611
+ if (isScope) {
612
+ s.state |= State.IsScope;
613
+ }
614
+ return s;
873
615
  }
874
- try {
875
- if (this.version === G.version) {
876
- return this.value;
616
+ DEFAULT_PULL() {
617
+ return this.nextValue;
618
+ }
619
+ /**
620
+ * 递归拉取负责建立以来链
621
+ */
622
+ pullRecurse(shouldLink = true) {
623
+ var _a, _b;
624
+ let downstream = G.PullingSignal;
625
+ const isScope = this.state & State.IsScope;
626
+ if (
627
+ // 1. 外部支持 link
628
+ shouldLink && // 2. 有下游
629
+ downstream && // 3. 下游是 watcher,不链接非 scope
630
+ !(downstream.state & State.LinkScopeOnly && !isScope)
631
+ ) {
632
+ Line.link(this, downstream);
877
633
  }
878
- this.state &= ~State.OutLink;
879
- // pullShallow 前重置 recEnd,让子 getter 重构订阅链表
880
- this.recEnd = undefined;
881
- Signal.Pulling = this;
882
- const v = this.pull();
883
- // 如果使用了 DEFAULT_PULL,处理一次 set 的取值后,替换回 customPull,如果有的话
884
- this.pull = this.customPull || this.DEFAULT_PULL;
885
- this.value = v;
886
- // 依赖上游的 版本号
887
- this.version = G.version;
888
- // if (this.value !== v) {
889
- // }
890
- return this.value;
891
- } catch (error) {
892
- console.error('计算属性报错这次不触发,后续状态可能出错', error);
893
- return this.value;
894
- } finally {
895
- // 本 getter 执行完成时上游 getter 通过 link,完成对下游 recLines 的更新
896
- const toDel = (_a = this.recEnd) === null || _a === void 0 ? void 0 : _a.nextRecLine;
897
- unlinkRecWithScope(toDel);
898
- if (shouldLink && downstream) {
899
- // 用于 scope 指示哪些节点依赖 scope 外部
900
- markOutLink(this, downstream);
634
+ try {
635
+ if (this.version === G.version) {
636
+ return this.value;
637
+ }
638
+ this.recEnd = null;
639
+ G.PullingSignal = this;
640
+ (_a = this.clean) == null ? void 0 : _a.call(this);
641
+ this.clean = null;
642
+ let v = this.pull();
643
+ if (isScope && typeof v === "function") {
644
+ const fn = v;
645
+ this.clean = () => runWithPulling(fn, null);
646
+ v = this.value;
647
+ }
648
+ this.pull = this.customPull || this.DEFAULT_PULL;
649
+ this.value = v;
650
+ this.version = G.version;
651
+ return this.value;
652
+ } catch (error) {
653
+ console.error("\u8BA1\u7B97\u5C5E\u6027\u62A5\u9519\u8FD9\u6B21\u4E0D\u89E6\u53D1\uFF0C\u540E\u7EED\u72B6\u6001\u53EF\u80FD\u51FA\u9519", error);
654
+ return this.value;
655
+ } finally {
656
+ const toDel = (_b = this.recEnd) == null ? void 0 : _b.nextRecLine;
657
+ unlinkRecWithScope(toDel);
658
+ G.PullingSignal = downstream;
901
659
  }
902
- Signal.Pulling = downstream;
903
660
  }
904
- }
905
- function Signal_$$$_pullDeep() {
906
- /*----------------- 有上游节点,通过 dfs 重新计算结果 -----------------*/
907
- const signal = this;
908
- // 优化执行
909
- if (!(signal.state & DirtyState)) {
910
- return this.value;
911
- }
912
- dfs(signal, {
913
- isUp: true,
914
- begin: ({
915
- node
916
- }) => {
917
- // console.log('begin', node.id);
918
- /**
919
- * 不需要检查
920
- * 1. 正在查
921
- * 2. 干净
922
- * 3. 放弃 或者为 scope 节点
923
- */
924
- if (node.state & State.Check || !(node.state & DirtyState) || node.isAbort()) {
925
- return true;
926
- }
927
- node.state |= State.Check;
928
- // 交给下游重新计算是否 引用外部节点
929
- node.state &= ~State.OutLink;
930
- },
931
- complete: ({
932
- node,
933
- notGoDeep: currentClean,
934
- walkedLine
935
- }) => {
936
- let noGoSibling = false;
937
- const last = walkedLine[walkedLine.length - 1];
938
- const downstream = last === null || last === void 0 ? void 0 : last.downstream;
939
- // 当前正在检查,生成检查屏障,同时避免重新标记 和
940
- if (currentClean) ;
941
- // 当前节点需要重新计算
942
- else if (node.state & State.Dirty) {
943
- // 优化:源节点变化,直接让下游节点重新计算
944
- if (!node.recStart && node.value !== node.nextValue) {
945
- node.markDownStreamsDirty();
946
- node.state &= ~State.Dirty;
947
- node.state &= ~State.Check;
948
- return;
661
+ pullDeep() {
662
+ const signal = this;
663
+ if (!(signal.state & DirtyState)) {
664
+ return this.value;
665
+ }
666
+ dfs(signal, {
667
+ isUp: true,
668
+ begin: ({ node }) => {
669
+ if (node.state & State.Check || !(node.state & DirtyState) || node.isDisabled()) {
670
+ return true;
949
671
  }
950
- // 预检数据
951
- else {
952
- const prevPulling = Signal.Pulling;
953
- Signal.Pulling = downstream;
954
- const prevValue = node.value;
955
- // 递归转用递归拉取,且不需要重建 link 因为dfs的前提就是上游节点依赖于 本节点
956
- node.pullRecurse(false);
957
- // dirty 传播, 由于本节点值已被计算出,因此消除 dirty
958
- if (prevValue !== node.value) {
672
+ node.state |= State.Check;
673
+ },
674
+ complete: ({ node, notGoDeep: currentClean, walkedLine }) => {
675
+ let noGoSibling = false;
676
+ const last = walkedLine[walkedLine.length - 1];
677
+ const downstream = last == null ? void 0 : last.downstream;
678
+ if (currentClean) ; else if (node.state & State.Dirty) {
679
+ if (!node.recStart && node.value !== node.nextValue) {
959
680
  node.markDownStreamsDirty();
681
+ node.state &= ~State.Dirty;
682
+ node.state &= ~State.Check;
683
+ return;
684
+ } else {
685
+ const prevPulling = G.PullingSignal;
686
+ G.PullingSignal = downstream;
687
+ const prevValue = node.value;
688
+ node.pullRecurse(false);
689
+ if (prevValue !== node.value) {
690
+ node.markDownStreamsDirty();
691
+ }
692
+ node.state &= ~State.Dirty;
693
+ G.PullingSignal = prevPulling;
694
+ noGoSibling = true;
960
695
  }
961
- node.state &= ~State.Dirty;
962
- Signal.Pulling = prevPulling;
963
- // 立刻返回父节点重新计算
964
- noGoSibling = true;
696
+ } else if (node.state & State.Unknown) {
697
+ node.state &= ~State.Unknown;
965
698
  }
699
+ node.version = G.version;
700
+ node.state &= ~State.Check;
701
+ return noGoSibling;
966
702
  }
967
- // 没被上游节点标记为 Dirty,说明是干净的
968
- else if (node.state & State.Unknown) {
969
- node.state &= ~State.Unknown;
970
- }
971
- node.version = G.version;
972
- node.state &= ~State.Check;
973
- if (downstream) {
974
- markOutLink(node, downstream);
975
- }
976
- return noGoSibling;
977
- }
978
- });
979
- return this.value;
980
- }
981
- function Signal_$$$_get() {
982
- if (this.isAbort()) {
703
+ });
983
704
  return this.value;
984
705
  }
985
- // 没有上游节点,应该通过递归重新建立
986
- if (!this.recStart) {
987
- return this.pullRecurse(true);
706
+ get v() {
707
+ if (this.isDisabled()) {
708
+ return this.value;
709
+ }
710
+ if (!this.recStart) {
711
+ return this.pullRecurse(true);
712
+ }
713
+ return this.pullDeep();
714
+ }
715
+ // pause() {
716
+ // this.state |= State.SelfPaused;
717
+ // }
718
+ // resume() {
719
+ // this.state &= ~State.SelfPaused;
720
+ // }
721
+ markDownStreamsDirty() {
722
+ let point = this.emitStart;
723
+ while (point != null) {
724
+ const downstream = point.downstream;
725
+ downstream.state |= State.Dirty;
726
+ downstream.state &= ~State.Unknown;
727
+ point = point.nextEmitLine;
728
+ }
988
729
  }
989
- // 有上游节点则采用 dfs 直接遍历,查看情况
990
- return this.pullDeep();
991
- }
992
- function Signal_$$$_markDownStreamsDirty() {
993
- let point = this.emitStart;
994
- while (point != null) {
995
- const downstream = point.downstream;
996
- downstream.state |= State.Dirty;
997
- downstream.state &= ~State.Unknown;
998
- point = point.nextEmitLine;
730
+ set v(v) {
731
+ if (this.isDisabled() || this.nextValue === v) {
732
+ return;
733
+ }
734
+ this.nextValue = v;
735
+ this.pull = this.DEFAULT_PULL;
736
+ G.version++;
737
+ markDeep(this);
999
738
  }
1000
- }
1001
- function Signal_$$$_set(v) {
1002
- if (this.isAbort() || this.nextValue === v) {
1003
- return;
739
+ runIfDirty() {
740
+ this.state & (State.Unknown | State.Dirty) && this.v;
1004
741
  }
1005
- this.nextValue = v;
1006
- // 手动设值后,采用默认拉取,能拉取到设置的值,拉取完成后在替换回 customPull
1007
- this.pull = this.DEFAULT_PULL;
1008
- G.version++;
1009
- markDeep(this);
1010
- }
1011
- function Signal_$$$_run(...args) {
1012
- if (args.length) {
1013
- return this.set(args[0]);
742
+ isDisabled() {
743
+ return (
744
+ // scope 被取消
745
+ this.scope && this.scope.state & State.ScopeAbort || // 是 scope 节点,且处于 ready 状态,不需要重复执行
746
+ this.state & State.IsScope && this.state & ScopeExecuted
747
+ );
1014
748
  }
1015
- return this.get();
1016
- }
1017
- function Signal_$$$_runIfDirty() {
1018
- this.state & (State.Unknown | State.Dirty) && this.run();
1019
- }
1020
- function Signal_$$$_isAbort() {
1021
- return (
1022
- // scope 被取消
1023
- this.scope && this.scope.state & State.ScopeAbort ||
1024
- // 是 scope 节点,且处于 ready 状态,不需要重复执行
1025
- this === this.scope && this.state & (State.ScopeAbort | State.ScopeReady)
1026
- );
1027
- }
1028
- Signal.Pulling = null;
1029
- function runWithPulling(fn, signal) {
1030
- const prevPulling = Signal.Pulling;
1031
- Signal.Pulling = signal;
1032
- fn();
1033
- Signal.Pulling = prevPulling;
1034
- }
749
+ };
750
+ _Signal.Pulling = null;
751
+ let Signal = _Signal;
1035
752
 
1036
- const DefaultCustomSignalOpt = {
1037
- scheduler: Scheduler.Sync,
1038
- isScope: false
753
+ var __defProp = Object.defineProperty;
754
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
755
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
756
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
757
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
758
+ var __spreadValues = (a, b) => {
759
+ for (var prop in b || (b = {}))
760
+ if (__hasOwnProp.call(b, prop))
761
+ __defNormalProp(a, prop, b[prop]);
762
+ if (__getOwnPropSymbols)
763
+ for (var prop of __getOwnPropSymbols(b)) {
764
+ if (__propIsEnum.call(b, prop))
765
+ __defNormalProp(a, prop, b[prop]);
766
+ }
767
+ return a;
1039
768
  };
1040
- const $ = (init, opt = {}) => {
1041
- let intiValue, pull;
769
+ ({
770
+ scheduler: Scheduler.Sync});
771
+ const $ = (init) => {
772
+ let intiValue, customPull;
1042
773
  if (init instanceof Function) {
1043
- intiValue = undefined;
1044
- pull = init;
774
+ intiValue = null;
775
+ customPull = init;
1045
776
  } else {
1046
777
  intiValue = init;
1047
778
  }
1048
- const signalOpt = {
1049
- ...DefaultCustomSignalOpt,
1050
- ...opt,
1051
- customPull: pull
1052
- };
1053
- const s = Signal.create(intiValue, signalOpt);
1054
- const bound = s.run.bind(s);
1055
- bound.ins = s;
1056
- Object.defineProperty(bound, 'v', {
1057
- get() {
1058
- return s.get();
1059
- },
1060
- set(v) {
1061
- return s.set(v);
1062
- }
779
+ const s = Signal.create(intiValue, {
780
+ scheduler: Scheduler.Sync,
781
+ isScope: false,
782
+ customPull
1063
783
  });
1064
- return bound;
784
+ return s;
1065
785
  };
1066
- const watch = (values, watcher, opt) => {
786
+ const effect = (customPull, depOrOpt, opt) => {
787
+ var _a;
788
+ const hasDep = Array.isArray(depOrOpt);
789
+ opt = hasDep ? opt || {} : depOrOpt || {};
790
+ if (!hasDep) {
791
+ const s2 = Signal.create(null, __spreadValues({
792
+ customPull,
793
+ scheduler: Scheduler.Sync,
794
+ isScope: true
795
+ }, opt));
796
+ s2.v;
797
+ const bound2 = dispose.bind(s2);
798
+ bound2.ins = s2;
799
+ return bound2;
800
+ }
1067
801
  let mounted = false;
1068
- const get = $(() => {
1069
- for (const get of values) {
1070
- get();
1071
- }
1072
- if (mounted) {
1073
- runWithPulling(watcher, undefined);
1074
- }
1075
- mounted = true;
1076
- }, opt);
1077
- get();
1078
- return get;
802
+ const deps = depOrOpt;
803
+ const immediate = deps.length === 0 ? true : (_a = opt.immediate) != null ? _a : true;
804
+ const vs = Array.from({ length: deps.length }, () => ({ old: null, val: null }));
805
+ const s = Signal.create(null, __spreadValues({
806
+ customPull() {
807
+ for (let i = 0; i < deps.length; i++) {
808
+ const value = deps[i].v;
809
+ vs[i].old = vs[i].val;
810
+ vs[i].val = value;
811
+ }
812
+ if (mounted || immediate) {
813
+ s.state |= State.LinkScopeOnly;
814
+ customPull(...vs);
815
+ s.state &= ~State.LinkScopeOnly;
816
+ }
817
+ mounted = true;
818
+ },
819
+ scheduler: Scheduler.Sync,
820
+ isScope: true
821
+ }, opt));
822
+ s.v;
823
+ const bound = dispose.bind(s);
824
+ bound.ins = s;
825
+ return bound;
1079
826
  };
1080
- const scope = fn => {
1081
- const s = Signal.create(undefined, {
1082
- customPull: fn,
827
+ const scope = (customPull) => {
828
+ const s = Signal.create(null, {
829
+ customPull,
830
+ scheduler: Scheduler.Sync,
1083
831
  isScope: true
1084
832
  });
1085
- s.get();
833
+ s.v;
1086
834
  s.state |= State.ScopeReady;
1087
- function dispose() {
1088
- s.state |= State.ScopeAbort;
1089
- const bound = handleOneTask.bind(undefined, s, []);
1090
- bound.index = G.scopeDisposeI++;
1091
- ideScheduler.pushTask(bound);
1092
- }
1093
- dispose.ins = s;
1094
- return dispose;
835
+ const bound = dispose.bind(s);
836
+ bound.ins = s;
837
+ return bound;
1095
838
  };
1096
- /**
1097
- * 数据变化时,自定义 触发订阅函数的时机
1098
- * @param {CustomSignalOpt} opt 配置如下:
1099
- * @prop scheduler: (runIfDirty, effect) => void 执行 runIfDirty 定制触发 effect 时机
1100
- * @prop scope: 用于统一释放 effect link 的作用域 默认是 defaultScope 可以全局获取
1101
- */
1102
- const customSignal = opt => {
1103
- return (init, innerOpt = {}) => {
1104
- const s = $(init, {
1105
- ...opt,
1106
- ...innerOpt
1107
- });
1108
- return s;
1109
- };
839
+ const customEffect = (opt) => {
840
+ return ((init, innerOpt = {}) => {
841
+ return effect(init, __spreadValues(__spreadValues({}, opt), innerOpt));
842
+ });
1110
843
  };
1111
844
 
1112
- export { $, Scheduler, customSignal, scheduler, scope, watch };
845
+ export { $, Scheduler, TaskQueue, clean, customEffect, effect, runWithPulling, scheduler, scope };
846
+ //# sourceMappingURL=aoye.esm.js.map