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