@zk-tech/bedrock 0.1.1 → 0.1.3
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/container-factory/index.cjs +254 -0
- package/dist/container-factory/index.cjs.map +1 -0
- package/dist/container-factory/index.d.cts +32 -0
- package/dist/container-factory/index.d.ts +32 -0
- package/dist/container-factory/index.js +232 -0
- package/dist/container-factory/index.js.map +1 -0
- package/dist/di/index.d.cts +7 -95
- package/dist/di/index.d.ts +7 -95
- package/dist/dynamic-dependency-service.interface-BrwqELkH.d.ts +40 -0
- package/dist/dynamic-dependency-service.interface-OUOyz9BD.d.cts +40 -0
- package/dist/instantiation-service-DjBf8Dy1.d.cts +59 -0
- package/dist/instantiation-service-V9JO6Ljg.d.ts +59 -0
- package/dist/{instantiation-service.interface-CVFMBUUD.d.cts → instantiation-service.interface-bshqO0aS.d.cts} +1 -1
- package/dist/{instantiation-service.interface-CVFMBUUD.d.ts → instantiation-service.interface-bshqO0aS.d.ts} +1 -1
- package/dist/launch/index.d.cts +1 -1
- package/dist/launch/index.d.ts +1 -1
- package/dist/services/dynamic-dependency/index.cjs +1583 -0
- package/dist/services/dynamic-dependency/index.cjs.map +1 -0
- package/dist/services/dynamic-dependency/index.d.cts +17 -0
- package/dist/services/dynamic-dependency/index.d.ts +17 -0
- package/dist/services/dynamic-dependency/index.js +1581 -0
- package/dist/services/dynamic-dependency/index.js.map +1 -0
- package/dist/type-BsqwDzaj.d.cts +39 -0
- package/dist/type-Bya55PZP.d.ts +39 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1581 @@
|
|
|
1
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
2
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
3
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
4
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
5
|
+
if (decorator = decorators[i])
|
|
6
|
+
result = (decorator(result)) || result;
|
|
7
|
+
return result;
|
|
8
|
+
};
|
|
9
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
10
|
+
|
|
11
|
+
// src/di/base.ts
|
|
12
|
+
var serviceIds = /* @__PURE__ */ new Map();
|
|
13
|
+
var DI_TARGET = "$di$target";
|
|
14
|
+
var DI_DEPENDENCIES = "$di$dependencies";
|
|
15
|
+
function getServiceDependencies(ctor) {
|
|
16
|
+
return ctor[DI_DEPENDENCIES] || [];
|
|
17
|
+
}
|
|
18
|
+
function setServiceDependency(id, ctor, index) {
|
|
19
|
+
if (ctor[DI_TARGET] === ctor) {
|
|
20
|
+
ctor[DI_DEPENDENCIES].push({ id, index });
|
|
21
|
+
} else {
|
|
22
|
+
ctor[DI_DEPENDENCIES] = [{ id, index }];
|
|
23
|
+
ctor[DI_TARGET] = ctor;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function createDecorator(serviceId) {
|
|
27
|
+
if (serviceIds.has(serviceId)) {
|
|
28
|
+
return serviceIds.get(serviceId);
|
|
29
|
+
}
|
|
30
|
+
const id = function(target, key, index) {
|
|
31
|
+
if (arguments.length !== 3) {
|
|
32
|
+
throw new Error("@IServiceName-decorator can only be used to decorate a parameter");
|
|
33
|
+
}
|
|
34
|
+
setServiceDependency(id, target, index);
|
|
35
|
+
};
|
|
36
|
+
id.toString = () => serviceId;
|
|
37
|
+
serviceIds.set(serviceId, id);
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/di/descriptor.ts
|
|
42
|
+
var SyncDescriptor = class {
|
|
43
|
+
constructor(ctor, staticArguments = [], supportsDelayedInstantiation = false) {
|
|
44
|
+
this.ctor = ctor;
|
|
45
|
+
this.staticArguments = staticArguments;
|
|
46
|
+
this.supportsDelayedInstantiation = supportsDelayedInstantiation;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/di/instantiation-service.interface.ts
|
|
51
|
+
var IInstantiationService = createDecorator("instantiation");
|
|
52
|
+
|
|
53
|
+
// src/_internal/logger.ts
|
|
54
|
+
var Logger = {
|
|
55
|
+
error(...data) {
|
|
56
|
+
if (typeof console.error === "function") {
|
|
57
|
+
console.error(...data);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
info(...data) {
|
|
61
|
+
if (typeof console.info === "function") {
|
|
62
|
+
console.info(...data);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
log(...data) {
|
|
66
|
+
if (typeof console.log === "function") {
|
|
67
|
+
console.log(...data);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
time(label) {
|
|
71
|
+
if (typeof console.time === "function") {
|
|
72
|
+
console.time(label);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
timeEnd(label) {
|
|
76
|
+
if (typeof console.timeEnd === "function") {
|
|
77
|
+
console.timeEnd(label);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
timeLog(label, ...data) {
|
|
81
|
+
if (typeof console.timeLog === "function") {
|
|
82
|
+
console.timeLog(label, ...data);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
timeStamp(label) {
|
|
86
|
+
if (typeof console.timeStamp === "function") {
|
|
87
|
+
console.timeStamp(label);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
trace(...data) {
|
|
91
|
+
if (typeof console.trace === "function") {
|
|
92
|
+
console.trace(...data);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
warn(...data) {
|
|
96
|
+
if (typeof console.warn === "function") {
|
|
97
|
+
console.warn(...data);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
profile(label) {
|
|
101
|
+
if (typeof console.profile === "function") {
|
|
102
|
+
console.profile(label);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
profileEnd(label) {
|
|
106
|
+
if (typeof console.profileEnd === "function") {
|
|
107
|
+
console.profileEnd(label);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// src/assert/assert.ts
|
|
113
|
+
function abort(reason) {
|
|
114
|
+
throw new Error(`lvAssert(${reason})`);
|
|
115
|
+
}
|
|
116
|
+
function lvAssert(expr, reason) {
|
|
117
|
+
if (!expr) {
|
|
118
|
+
abort(reason ?? "#expr is false");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/dispose/disposable-t.ts
|
|
123
|
+
var SafeDisposable = class {
|
|
124
|
+
constructor(value) {
|
|
125
|
+
this._value = value;
|
|
126
|
+
}
|
|
127
|
+
get value() {
|
|
128
|
+
return this._value;
|
|
129
|
+
}
|
|
130
|
+
isEmpty() {
|
|
131
|
+
return this._value === void 0;
|
|
132
|
+
}
|
|
133
|
+
dispose() {
|
|
134
|
+
if (!this._value) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
this._value.dispose();
|
|
138
|
+
this._value = void 0;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// src/dispose/disposable-utils.ts
|
|
143
|
+
function makeSafeDisposable(fn) {
|
|
144
|
+
const disposable = new SafeDisposable({
|
|
145
|
+
dispose: fn
|
|
146
|
+
});
|
|
147
|
+
return disposable;
|
|
148
|
+
}
|
|
149
|
+
function isDisposable(thing) {
|
|
150
|
+
return typeof thing.dispose === "function" && thing.dispose.length === 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/scheduler/core/task.ts
|
|
154
|
+
var Task = class {
|
|
155
|
+
constructor(callback, _startTime, _expirationTime) {
|
|
156
|
+
this._startTime = _startTime;
|
|
157
|
+
this._expirationTime = _expirationTime;
|
|
158
|
+
this._sortIndex = -1;
|
|
159
|
+
this._callback = callback;
|
|
160
|
+
}
|
|
161
|
+
getCallback() {
|
|
162
|
+
return this._callback;
|
|
163
|
+
}
|
|
164
|
+
setCallback(callback) {
|
|
165
|
+
lvAssert(this._callback === void 0, "cant overlay callback.");
|
|
166
|
+
this._callback = callback;
|
|
167
|
+
}
|
|
168
|
+
clearCallback() {
|
|
169
|
+
this._callback = void 0;
|
|
170
|
+
}
|
|
171
|
+
getStartTime() {
|
|
172
|
+
return this._startTime;
|
|
173
|
+
}
|
|
174
|
+
setStartTime(startTime) {
|
|
175
|
+
this._startTime = startTime;
|
|
176
|
+
}
|
|
177
|
+
getExpirationTime() {
|
|
178
|
+
return this._expirationTime;
|
|
179
|
+
}
|
|
180
|
+
setExpirationTime(expirationTime) {
|
|
181
|
+
this._expirationTime = expirationTime;
|
|
182
|
+
}
|
|
183
|
+
setSortIndex(index) {
|
|
184
|
+
this._sortIndex = index;
|
|
185
|
+
}
|
|
186
|
+
getSortIndex() {
|
|
187
|
+
return this._sortIndex;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// src/scheduler/core/utils.ts
|
|
192
|
+
var maxSigned31BitInt = 1073741823;
|
|
193
|
+
var IMMEDIATE_PRIORITY_TIMEOUT = -1;
|
|
194
|
+
var USER_BLOCKING_PRIORITY_TIMEOUT = 250;
|
|
195
|
+
var NORMAL_PRIORITY_TIMEOUT = 5e3;
|
|
196
|
+
var LOW_PRIORITY_TIMEOUT = 1e4;
|
|
197
|
+
var IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt;
|
|
198
|
+
function getCurrentTime() {
|
|
199
|
+
return Date.now();
|
|
200
|
+
}
|
|
201
|
+
function getTimeout(priorityLevel = 2 /* NormalPriority */) {
|
|
202
|
+
switch (priorityLevel) {
|
|
203
|
+
case 0 /* ImmediatePriority */:
|
|
204
|
+
return IMMEDIATE_PRIORITY_TIMEOUT;
|
|
205
|
+
case 1 /* UserBlockingPriority */:
|
|
206
|
+
return USER_BLOCKING_PRIORITY_TIMEOUT;
|
|
207
|
+
case 4 /* IdlePriority */:
|
|
208
|
+
return IDLE_PRIORITY_TIMEOUT;
|
|
209
|
+
case 3 /* LowPriority */:
|
|
210
|
+
return LOW_PRIORITY_TIMEOUT;
|
|
211
|
+
case 2 /* NormalPriority */:
|
|
212
|
+
default:
|
|
213
|
+
return NORMAL_PRIORITY_TIMEOUT;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function makeTask(callback, options = {}) {
|
|
217
|
+
const currentTime = getCurrentTime();
|
|
218
|
+
const delay = options.delay ?? 0;
|
|
219
|
+
const timeout = getTimeout(options.priorityLevel);
|
|
220
|
+
const startTime = delay + currentTime;
|
|
221
|
+
const expirationTime = startTime + timeout;
|
|
222
|
+
const newTask = new Task(callback, startTime, expirationTime);
|
|
223
|
+
return newTask;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/scheduler/core/chunk-scheduler.ts
|
|
227
|
+
var ChunkScheduler = class {
|
|
228
|
+
constructor(_task, _scheduler) {
|
|
229
|
+
this._task = _task;
|
|
230
|
+
this._scheduler = _scheduler;
|
|
231
|
+
this._needContinue = false;
|
|
232
|
+
}
|
|
233
|
+
get needContinue() {
|
|
234
|
+
return this._needContinue;
|
|
235
|
+
}
|
|
236
|
+
continueExecute(callback) {
|
|
237
|
+
this._needContinue = true;
|
|
238
|
+
this._task.setCallback(callback);
|
|
239
|
+
}
|
|
240
|
+
execute(callback, options = {}) {
|
|
241
|
+
const newTask = makeTask(callback, options);
|
|
242
|
+
this._scheduler.addTask(newTask);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// src/scheduler/core/actuator.ts
|
|
247
|
+
var Actuator = class {
|
|
248
|
+
constructor(_taskQueue, _scheduler) {
|
|
249
|
+
this._taskQueue = _taskQueue;
|
|
250
|
+
this._scheduler = _scheduler;
|
|
251
|
+
}
|
|
252
|
+
workLoop(hasTimeRemaining, initialTime, deadline) {
|
|
253
|
+
let currentTime = initialTime;
|
|
254
|
+
this._taskQueue.advance(currentTime);
|
|
255
|
+
let currentTask = this._taskQueue.waitingTasks.peek();
|
|
256
|
+
while (currentTask !== null) {
|
|
257
|
+
if (currentTask.getExpirationTime() > currentTime && (!hasTimeRemaining || this._scheduler.shouldYieldToHost(deadline))) {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
if (currentTask.getCallback() === void 0) {
|
|
261
|
+
this._taskQueue.waitingTasks.remove();
|
|
262
|
+
} else {
|
|
263
|
+
const callback = currentTask.getCallback();
|
|
264
|
+
const didUserCallbackTimeout = currentTask.getExpirationTime() <= currentTime;
|
|
265
|
+
const remainingTime = deadline - currentTime;
|
|
266
|
+
currentTask.clearCallback();
|
|
267
|
+
const chunkInvoker = new ChunkScheduler(currentTask, this._scheduler);
|
|
268
|
+
callback(chunkInvoker, didUserCallbackTimeout, remainingTime);
|
|
269
|
+
if (!chunkInvoker.needContinue) {
|
|
270
|
+
this._taskQueue.waitingTasks.remove();
|
|
271
|
+
}
|
|
272
|
+
currentTime = getCurrentTime();
|
|
273
|
+
this._taskQueue.advance(currentTime);
|
|
274
|
+
}
|
|
275
|
+
currentTask = this._taskQueue.waitingTasks.peek();
|
|
276
|
+
}
|
|
277
|
+
if (currentTask !== null) {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
this._scheduler.requestHostTimeout(currentTime);
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// src/structure/min-heap.ts
|
|
286
|
+
var MinHeap = class {
|
|
287
|
+
constructor(compareFunction) {
|
|
288
|
+
this._heap = [];
|
|
289
|
+
if (compareFunction) {
|
|
290
|
+
this._compare = compareFunction;
|
|
291
|
+
} else {
|
|
292
|
+
this._compare = (a, b) => {
|
|
293
|
+
if (a < b) return -1;
|
|
294
|
+
if (a > b) return 1;
|
|
295
|
+
return 0;
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
insert(value) {
|
|
300
|
+
this._heap.push(value);
|
|
301
|
+
this._siftUp();
|
|
302
|
+
}
|
|
303
|
+
peek() {
|
|
304
|
+
return this._heap.length > 0 ? this._heap[0] : null;
|
|
305
|
+
}
|
|
306
|
+
remove() {
|
|
307
|
+
if (this._heap.length === 0) return null;
|
|
308
|
+
if (this._heap.length === 1) return this._heap.pop();
|
|
309
|
+
const item = this._heap[0];
|
|
310
|
+
this._heap[0] = this._heap.pop();
|
|
311
|
+
this._siftDown();
|
|
312
|
+
return item;
|
|
313
|
+
}
|
|
314
|
+
size() {
|
|
315
|
+
return this._heap.length;
|
|
316
|
+
}
|
|
317
|
+
clear() {
|
|
318
|
+
this._heap.length = 0;
|
|
319
|
+
}
|
|
320
|
+
_getLeftChildIndex(parentIndex) {
|
|
321
|
+
return 2 * parentIndex + 1;
|
|
322
|
+
}
|
|
323
|
+
_getRightChildIndex(parentIndex) {
|
|
324
|
+
return 2 * parentIndex + 2;
|
|
325
|
+
}
|
|
326
|
+
_getParentIndex(childIndex) {
|
|
327
|
+
return Math.floor((childIndex - 1) / 2);
|
|
328
|
+
}
|
|
329
|
+
_swap(indexOne, indexTwo) {
|
|
330
|
+
[this._heap[indexOne], this._heap[indexTwo]] = [this._heap[indexTwo], this._heap[indexOne]];
|
|
331
|
+
}
|
|
332
|
+
_siftUp() {
|
|
333
|
+
let index = this._heap.length - 1;
|
|
334
|
+
while (index > 0 && this._compare(this._heap[this._getParentIndex(index)], this._heap[index]) > 0) {
|
|
335
|
+
const parentIndex = this._getParentIndex(index);
|
|
336
|
+
this._swap(index, parentIndex);
|
|
337
|
+
index = parentIndex;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
_siftDown() {
|
|
341
|
+
let index = 0;
|
|
342
|
+
let smallerChildIndex = this._getLeftChildIndex(index);
|
|
343
|
+
while (smallerChildIndex < this._heap.length) {
|
|
344
|
+
const rightChildIndex = this._getRightChildIndex(index);
|
|
345
|
+
if (rightChildIndex < this._heap.length && this._compare(this._heap[rightChildIndex], this._heap[smallerChildIndex]) < 0) {
|
|
346
|
+
smallerChildIndex = rightChildIndex;
|
|
347
|
+
}
|
|
348
|
+
if (this._compare(this._heap[index], this._heap[smallerChildIndex]) <= 0) {
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
this._swap(index, smallerChildIndex);
|
|
352
|
+
index = smallerChildIndex;
|
|
353
|
+
smallerChildIndex = this._getLeftChildIndex(index);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
// src/scheduler/core/task-queue.ts
|
|
359
|
+
function compare(lhs, rhs) {
|
|
360
|
+
return lhs.getSortIndex() - rhs.getSortIndex();
|
|
361
|
+
}
|
|
362
|
+
var TaskQueue = class {
|
|
363
|
+
constructor() {
|
|
364
|
+
// 延时任务
|
|
365
|
+
this._timerTasks = new MinHeap(compare);
|
|
366
|
+
// 等待执行的任务
|
|
367
|
+
this._waitingTasks = new MinHeap(compare);
|
|
368
|
+
}
|
|
369
|
+
get timerTasks() {
|
|
370
|
+
return this._timerTasks;
|
|
371
|
+
}
|
|
372
|
+
get waitingTasks() {
|
|
373
|
+
return this._waitingTasks;
|
|
374
|
+
}
|
|
375
|
+
advance(currentTime) {
|
|
376
|
+
let task = this._timerTasks.peek();
|
|
377
|
+
while (task !== null) {
|
|
378
|
+
if (task.getCallback() === null) {
|
|
379
|
+
this._timerTasks.remove();
|
|
380
|
+
} else if (task.getStartTime() <= currentTime) {
|
|
381
|
+
this._timerTasks.remove();
|
|
382
|
+
task.setSortIndex(task.getExpirationTime());
|
|
383
|
+
this._waitingTasks.insert(task);
|
|
384
|
+
} else {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
task = this._timerTasks.peek();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// src/scheduler/executor/abstract-executor.ts
|
|
393
|
+
var AbstractExecutor = class {
|
|
394
|
+
constructor() {
|
|
395
|
+
this._timeoutId = -1;
|
|
396
|
+
this._deadline = 0;
|
|
397
|
+
this._yieldInterval = 16;
|
|
398
|
+
}
|
|
399
|
+
get deadline() {
|
|
400
|
+
return this._deadline;
|
|
401
|
+
}
|
|
402
|
+
setFrameRate(fps) {
|
|
403
|
+
lvAssert(fps > 0 && fps <= 125);
|
|
404
|
+
this._yieldInterval = Math.floor(1e3 / fps);
|
|
405
|
+
}
|
|
406
|
+
resetFrameRate() {
|
|
407
|
+
this._yieldInterval = 16;
|
|
408
|
+
}
|
|
409
|
+
requestHostTimeout(fn, delayMs) {
|
|
410
|
+
lvAssert(this._timeoutId === -1, "has request host timeout.");
|
|
411
|
+
clearTimeout(this._timeoutId);
|
|
412
|
+
this._timeoutId = setTimeout(() => {
|
|
413
|
+
this._timeoutId = -1;
|
|
414
|
+
fn();
|
|
415
|
+
}, delayMs);
|
|
416
|
+
}
|
|
417
|
+
cancelHostTimeout() {
|
|
418
|
+
clearTimeout(this._timeoutId);
|
|
419
|
+
this._timeoutId = -1;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// src/scheduler/executor/idle-callback-executor.ts
|
|
424
|
+
var IdleCallbackExecutor = class extends AbstractExecutor {
|
|
425
|
+
constructor() {
|
|
426
|
+
super();
|
|
427
|
+
this._flushCallback = () => {
|
|
428
|
+
if (!this._scheduledCallback) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
const currentTime = getCurrentTime();
|
|
432
|
+
const deadline = currentTime + this._yieldInterval;
|
|
433
|
+
try {
|
|
434
|
+
const hasMoreWork = this._scheduledCallback(true, currentTime, deadline);
|
|
435
|
+
if (!hasMoreWork) {
|
|
436
|
+
this._scheduledCallback = void 0;
|
|
437
|
+
this._disposable = void 0;
|
|
438
|
+
} else {
|
|
439
|
+
this._disposable = this._runWhenIdle(this._flushCallback);
|
|
440
|
+
}
|
|
441
|
+
} catch (err) {
|
|
442
|
+
this._disposable = this._runWhenIdle(this._flushCallback);
|
|
443
|
+
throw err;
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
if (typeof requestIdleCallback !== "function" || typeof cancelIdleCallback !== "function") {
|
|
447
|
+
this._runWhenIdle = (runner) => {
|
|
448
|
+
let disposed = false;
|
|
449
|
+
setTimeout(() => {
|
|
450
|
+
if (disposed) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const end = Date.now() + 15;
|
|
454
|
+
runner(
|
|
455
|
+
Object.freeze({
|
|
456
|
+
didTimeout: true,
|
|
457
|
+
timeRemaining() {
|
|
458
|
+
return Math.max(0, end - Date.now());
|
|
459
|
+
}
|
|
460
|
+
})
|
|
461
|
+
);
|
|
462
|
+
});
|
|
463
|
+
return {
|
|
464
|
+
dispose() {
|
|
465
|
+
if (disposed) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
disposed = true;
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
};
|
|
472
|
+
} else {
|
|
473
|
+
this._runWhenIdle = (runner, timeout) => {
|
|
474
|
+
const handle = requestIdleCallback(
|
|
475
|
+
runner,
|
|
476
|
+
typeof timeout === "number" ? { timeout } : void 0
|
|
477
|
+
);
|
|
478
|
+
let disposed = false;
|
|
479
|
+
return {
|
|
480
|
+
dispose() {
|
|
481
|
+
if (disposed) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
disposed = true;
|
|
485
|
+
cancelIdleCallback(handle);
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
requestHostCallback(fn) {
|
|
492
|
+
this._scheduledCallback = fn;
|
|
493
|
+
if (!this._disposable) {
|
|
494
|
+
this._disposable = this._runWhenIdle(this._flushCallback);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
cancelHostCallback() {
|
|
498
|
+
this._disposable?.dispose();
|
|
499
|
+
this._scheduledCallback = void 0;
|
|
500
|
+
this._disposable = void 0;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
// src/scheduler/executor/post-message-executor.ts
|
|
505
|
+
var PostMessageExecutor = class extends AbstractExecutor {
|
|
506
|
+
constructor() {
|
|
507
|
+
super();
|
|
508
|
+
this._isMessageLoopRunning = false;
|
|
509
|
+
this._channel = new MessageChannel();
|
|
510
|
+
this._flushCallback = () => {
|
|
511
|
+
if (!this._scheduledCallback) {
|
|
512
|
+
this._isMessageLoopRunning = false;
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const currentTime = getCurrentTime();
|
|
516
|
+
const deadline = currentTime + this._yieldInterval;
|
|
517
|
+
try {
|
|
518
|
+
const hasMoreWork = this._scheduledCallback(true, currentTime, deadline);
|
|
519
|
+
if (!hasMoreWork) {
|
|
520
|
+
this._isMessageLoopRunning = false;
|
|
521
|
+
this._scheduledCallback = void 0;
|
|
522
|
+
} else {
|
|
523
|
+
this._channel.port2.postMessage(null);
|
|
524
|
+
}
|
|
525
|
+
} catch (err) {
|
|
526
|
+
this._channel.port2.postMessage(null);
|
|
527
|
+
throw err;
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
this._channel.port1.onmessage = () => {
|
|
531
|
+
this._flushCallback();
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
requestHostCallback(fn) {
|
|
535
|
+
this._scheduledCallback = fn;
|
|
536
|
+
if (!this._isMessageLoopRunning) {
|
|
537
|
+
this._isMessageLoopRunning = true;
|
|
538
|
+
this._channel.port2.postMessage(null);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
cancelHostCallback() {
|
|
542
|
+
this._scheduledCallback = void 0;
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
// src/scheduler/executor/make-executor.ts
|
|
547
|
+
function makeExecutor() {
|
|
548
|
+
try {
|
|
549
|
+
if (global.window) {
|
|
550
|
+
return new PostMessageExecutor();
|
|
551
|
+
}
|
|
552
|
+
} catch (e) {
|
|
553
|
+
}
|
|
554
|
+
return new IdleCallbackExecutor();
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// src/scheduler/core/scheduler.ts
|
|
558
|
+
var Scheduler = class {
|
|
559
|
+
constructor() {
|
|
560
|
+
this._isHostTimeoutScheduled = false;
|
|
561
|
+
this._isHostCallbackScheduled = false;
|
|
562
|
+
this._isWorking = false;
|
|
563
|
+
this._enableInputPending = true;
|
|
564
|
+
this._executor = makeExecutor();
|
|
565
|
+
this._taskQueue = new TaskQueue();
|
|
566
|
+
this._actuator = new Actuator(this._taskQueue, this);
|
|
567
|
+
/**
|
|
568
|
+
* 是否需要让出事件给宿主
|
|
569
|
+
*/
|
|
570
|
+
this.shouldYieldToHost = (() => {
|
|
571
|
+
try {
|
|
572
|
+
if (global.navigator?.scheduling?.isInputPending !== void 0) {
|
|
573
|
+
const { scheduling } = global.navigator;
|
|
574
|
+
return (deadline) => {
|
|
575
|
+
if (this._enableInputPending && scheduling.isInputPending()) {
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
return getCurrentTime() >= deadline;
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
} catch (e) {
|
|
582
|
+
}
|
|
583
|
+
return (deadline) => {
|
|
584
|
+
return getCurrentTime() >= deadline;
|
|
585
|
+
};
|
|
586
|
+
})();
|
|
587
|
+
this._handleHostTimeout = () => {
|
|
588
|
+
this._isHostTimeoutScheduled = false;
|
|
589
|
+
const currentTime = getCurrentTime();
|
|
590
|
+
this._taskQueue.advance(currentTime);
|
|
591
|
+
if (this._isHostCallbackScheduled) {
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
if (this._taskQueue.waitingTasks.peek() !== null) {
|
|
595
|
+
this._isHostCallbackScheduled = true;
|
|
596
|
+
this._executor.requestHostCallback(this._handleHostCallback);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
this._requestHostTimeout(currentTime);
|
|
600
|
+
};
|
|
601
|
+
this._handleHostCallback = (hasTimeRemaining, initialTime, deadline) => {
|
|
602
|
+
this._isHostCallbackScheduled = false;
|
|
603
|
+
if (this._isHostTimeoutScheduled) {
|
|
604
|
+
this._isHostTimeoutScheduled = false;
|
|
605
|
+
this._executor.cancelHostTimeout();
|
|
606
|
+
}
|
|
607
|
+
this._isWorking = true;
|
|
608
|
+
try {
|
|
609
|
+
return this._actuator.workLoop(hasTimeRemaining, initialTime, deadline);
|
|
610
|
+
} finally {
|
|
611
|
+
this._isWorking = false;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
get taskQueue() {
|
|
616
|
+
return this._taskQueue;
|
|
617
|
+
}
|
|
618
|
+
get executor() {
|
|
619
|
+
return this._executor;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* 设置是否开启InputPending
|
|
623
|
+
*/
|
|
624
|
+
setEnableInputPending(val) {
|
|
625
|
+
this._enableInputPending = val;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* 调度器中添加任务
|
|
629
|
+
*/
|
|
630
|
+
addTask(task) {
|
|
631
|
+
const currentTime = getCurrentTime();
|
|
632
|
+
if (task.getStartTime() > currentTime) {
|
|
633
|
+
task.setSortIndex(task.getStartTime());
|
|
634
|
+
this._taskQueue.timerTasks.insert(task);
|
|
635
|
+
if (this._taskQueue.waitingTasks.peek() === null && task === this._taskQueue.timerTasks.peek()) {
|
|
636
|
+
if (this._isHostTimeoutScheduled) {
|
|
637
|
+
this._executor.cancelHostTimeout();
|
|
638
|
+
} else {
|
|
639
|
+
this._isHostTimeoutScheduled = true;
|
|
640
|
+
}
|
|
641
|
+
this._executor.requestHostTimeout(this._handleHostTimeout, task.getStartTime() - currentTime);
|
|
642
|
+
}
|
|
643
|
+
} else {
|
|
644
|
+
task.setSortIndex(task.getExpirationTime());
|
|
645
|
+
this._taskQueue.waitingTasks.insert(task);
|
|
646
|
+
if (!this._isHostCallbackScheduled && !this._isWorking) {
|
|
647
|
+
this._isHostCallbackScheduled = true;
|
|
648
|
+
this._executor.requestHostCallback(this._handleHostCallback);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* 尝试启动异步任务调度
|
|
654
|
+
*/
|
|
655
|
+
requestHostTimeout(currentTime) {
|
|
656
|
+
this._requestHostTimeout(currentTime);
|
|
657
|
+
}
|
|
658
|
+
_requestHostTimeout(currentTime) {
|
|
659
|
+
lvAssert(!this._isHostCallbackScheduled);
|
|
660
|
+
lvAssert(!this._isHostTimeoutScheduled);
|
|
661
|
+
const firstTimerTask = this._taskQueue.timerTasks.peek();
|
|
662
|
+
if (firstTimerTask !== null) {
|
|
663
|
+
this._isHostTimeoutScheduled = true;
|
|
664
|
+
this._executor.requestHostTimeout(this._handleHostTimeout, firstTimerTask.getStartTime() - currentTime);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
var scheduler;
|
|
669
|
+
function getScheduler() {
|
|
670
|
+
if (!scheduler) {
|
|
671
|
+
scheduler = new Scheduler();
|
|
672
|
+
}
|
|
673
|
+
return scheduler;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/scheduler/callback-token.ts
|
|
677
|
+
var CallbackToken = class {
|
|
678
|
+
constructor(_task) {
|
|
679
|
+
this._task = _task;
|
|
680
|
+
}
|
|
681
|
+
dispose() {
|
|
682
|
+
this._task.clearCallback();
|
|
683
|
+
}
|
|
684
|
+
updatePriorityLevel(priorityLevel) {
|
|
685
|
+
const callback = this._task.getCallback();
|
|
686
|
+
if (!callback) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
this._task.clearCallback();
|
|
690
|
+
const newTask = makeTask(callback, {
|
|
691
|
+
priorityLevel
|
|
692
|
+
});
|
|
693
|
+
const startTime = this._task.getStartTime();
|
|
694
|
+
const timeout = getTimeout(priorityLevel);
|
|
695
|
+
const expirationTime = startTime + timeout;
|
|
696
|
+
newTask.setStartTime(startTime);
|
|
697
|
+
newTask.setExpirationTime(expirationTime);
|
|
698
|
+
getScheduler().addTask(newTask);
|
|
699
|
+
this._task = newTask;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
|
|
703
|
+
// src/scheduler/lv-scheduler-callback.ts
|
|
704
|
+
function lvSchedulerCallback(callback, options = {}) {
|
|
705
|
+
const newTask = makeTask(callback, options);
|
|
706
|
+
getScheduler().addTask(newTask);
|
|
707
|
+
return new CallbackToken(newTask);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// src/structure/linked-list.ts
|
|
711
|
+
var ListNode = class {
|
|
712
|
+
constructor(value, next = null, prev = null) {
|
|
713
|
+
this.value = value;
|
|
714
|
+
this.next = next;
|
|
715
|
+
this.prev = prev;
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
var LinkedList = class {
|
|
719
|
+
constructor() {
|
|
720
|
+
this._head = null;
|
|
721
|
+
this._tail = null;
|
|
722
|
+
this._count = 0;
|
|
723
|
+
}
|
|
724
|
+
get size() {
|
|
725
|
+
return this._count;
|
|
726
|
+
}
|
|
727
|
+
get firstNode() {
|
|
728
|
+
return this._head;
|
|
729
|
+
}
|
|
730
|
+
isEmpty() {
|
|
731
|
+
return this._head === null;
|
|
732
|
+
}
|
|
733
|
+
clear() {
|
|
734
|
+
let current = this._head;
|
|
735
|
+
while (current !== null) {
|
|
736
|
+
const next = current.next;
|
|
737
|
+
current.prev = null;
|
|
738
|
+
current.next = null;
|
|
739
|
+
current = next;
|
|
740
|
+
}
|
|
741
|
+
this._head = null;
|
|
742
|
+
this._tail = null;
|
|
743
|
+
this._count = 0;
|
|
744
|
+
}
|
|
745
|
+
unshift(value) {
|
|
746
|
+
const node = new ListNode(value);
|
|
747
|
+
if (this.isEmpty()) {
|
|
748
|
+
this._head = node;
|
|
749
|
+
this._tail = node;
|
|
750
|
+
} else {
|
|
751
|
+
const oldHead = this._head;
|
|
752
|
+
this._head = node;
|
|
753
|
+
node.next = oldHead;
|
|
754
|
+
oldHead.prev = node;
|
|
755
|
+
}
|
|
756
|
+
this._count++;
|
|
757
|
+
return this;
|
|
758
|
+
}
|
|
759
|
+
push(value) {
|
|
760
|
+
const node = new ListNode(value);
|
|
761
|
+
if (this.isEmpty()) {
|
|
762
|
+
this._head = node;
|
|
763
|
+
this._tail = node;
|
|
764
|
+
} else {
|
|
765
|
+
const oldTail = this._tail;
|
|
766
|
+
this._tail = node;
|
|
767
|
+
node.prev = oldTail;
|
|
768
|
+
oldTail.next = node;
|
|
769
|
+
}
|
|
770
|
+
this._count++;
|
|
771
|
+
return this;
|
|
772
|
+
}
|
|
773
|
+
shift() {
|
|
774
|
+
if (this.isEmpty()) {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
const node = this._head;
|
|
778
|
+
const value = node.value;
|
|
779
|
+
this._remove(node);
|
|
780
|
+
return value;
|
|
781
|
+
}
|
|
782
|
+
pop() {
|
|
783
|
+
if (this.isEmpty()) {
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
const node = this._tail;
|
|
787
|
+
const value = node.value;
|
|
788
|
+
this._remove(node);
|
|
789
|
+
return value;
|
|
790
|
+
}
|
|
791
|
+
toArray() {
|
|
792
|
+
const result = [];
|
|
793
|
+
for (const value of this) {
|
|
794
|
+
result.push(value);
|
|
795
|
+
}
|
|
796
|
+
return result;
|
|
797
|
+
}
|
|
798
|
+
*[Symbol.iterator]() {
|
|
799
|
+
let current = this._head;
|
|
800
|
+
while (current !== null) {
|
|
801
|
+
yield current.value;
|
|
802
|
+
current = current.next;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
_remove(node) {
|
|
806
|
+
if (node.prev === null && node.next === null && node !== this._head && node !== this._tail) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
if (node === this._head) {
|
|
810
|
+
this._head = node.next;
|
|
811
|
+
if (this._head) {
|
|
812
|
+
this._head.prev = null;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (node === this._tail) {
|
|
816
|
+
this._tail = node.prev;
|
|
817
|
+
if (this._tail) {
|
|
818
|
+
this._tail.next = null;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (node.prev) {
|
|
822
|
+
node.prev.next = node.next;
|
|
823
|
+
}
|
|
824
|
+
if (node.next) {
|
|
825
|
+
node.next.prev = node.prev;
|
|
826
|
+
}
|
|
827
|
+
node.prev = null;
|
|
828
|
+
node.next = null;
|
|
829
|
+
this._count--;
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
// src/event/disposable-linked-list.ts
|
|
834
|
+
var DisposableLinkedList = class extends LinkedList {
|
|
835
|
+
unshiftAndGetDisposableNode(value) {
|
|
836
|
+
this.unshift(value);
|
|
837
|
+
const node = this._head;
|
|
838
|
+
let hasRemoved = false;
|
|
839
|
+
return () => {
|
|
840
|
+
if (!hasRemoved) {
|
|
841
|
+
hasRemoved = true;
|
|
842
|
+
super._remove(node);
|
|
843
|
+
}
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
pushAndGetDisposableNode(value) {
|
|
847
|
+
this.push(value);
|
|
848
|
+
const node = this._tail;
|
|
849
|
+
let hasRemoved = false;
|
|
850
|
+
return () => {
|
|
851
|
+
if (!hasRemoved) {
|
|
852
|
+
hasRemoved = true;
|
|
853
|
+
super._remove(node);
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
|
|
859
|
+
// src/event/error-handler.ts
|
|
860
|
+
function asyncUnexpectedError(e) {
|
|
861
|
+
setTimeout(() => {
|
|
862
|
+
throw e;
|
|
863
|
+
}, 0);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// src/event/emitter.ts
|
|
867
|
+
var Listener = class {
|
|
868
|
+
constructor(callback, callbackThis) {
|
|
869
|
+
this._callback = callback;
|
|
870
|
+
this._callbackThis = callbackThis;
|
|
871
|
+
}
|
|
872
|
+
invoke(...args) {
|
|
873
|
+
this._callback.call(this._callbackThis, ...args);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
var EventDeliveryQueueElement = class {
|
|
877
|
+
constructor(emitter, listener, event) {
|
|
878
|
+
this.emitter = emitter;
|
|
879
|
+
this.listener = listener;
|
|
880
|
+
this.event = event;
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
var EventDeliveryQueue = class {
|
|
884
|
+
constructor(_onListenerError = asyncUnexpectedError) {
|
|
885
|
+
this._onListenerError = _onListenerError;
|
|
886
|
+
this._queue = new DisposableLinkedList();
|
|
887
|
+
}
|
|
888
|
+
get size() {
|
|
889
|
+
return this._queue.size;
|
|
890
|
+
}
|
|
891
|
+
push(emitter, listener, event) {
|
|
892
|
+
this._queue.push(new EventDeliveryQueueElement(emitter, listener, event));
|
|
893
|
+
}
|
|
894
|
+
clear(emitter) {
|
|
895
|
+
const newQueue = new DisposableLinkedList();
|
|
896
|
+
for (const element of this._queue) {
|
|
897
|
+
if (element.emitter !== emitter) {
|
|
898
|
+
newQueue.push(element);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
this._queue = newQueue;
|
|
902
|
+
}
|
|
903
|
+
deliver() {
|
|
904
|
+
while (this._queue.size > 0) {
|
|
905
|
+
const element = this._queue.shift();
|
|
906
|
+
try {
|
|
907
|
+
element.listener.invoke(...element.event);
|
|
908
|
+
} catch (e) {
|
|
909
|
+
this._onListenerError(e);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
var Emitter = class {
|
|
915
|
+
constructor(options) {
|
|
916
|
+
this._disposed = false;
|
|
917
|
+
this._options = options;
|
|
918
|
+
}
|
|
919
|
+
get event() {
|
|
920
|
+
if (this._event) {
|
|
921
|
+
return this._event;
|
|
922
|
+
}
|
|
923
|
+
this._event = (callback, thisArgs) => {
|
|
924
|
+
const listener = new Listener(callback, thisArgs);
|
|
925
|
+
if (!this._listeners) {
|
|
926
|
+
this._listeners = new DisposableLinkedList();
|
|
927
|
+
}
|
|
928
|
+
const removeListener = this._listeners.pushAndGetDisposableNode(listener);
|
|
929
|
+
if (this._options?.onAddListener) {
|
|
930
|
+
this._options.onAddListener(this, callback, thisArgs);
|
|
931
|
+
}
|
|
932
|
+
const result = () => {
|
|
933
|
+
if (!this._disposed) {
|
|
934
|
+
removeListener();
|
|
935
|
+
if (this._options?.onRemoveListener) {
|
|
936
|
+
this._options.onRemoveListener(this, callback, thisArgs);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
return makeSafeDisposable(result);
|
|
941
|
+
};
|
|
942
|
+
return this._event;
|
|
943
|
+
}
|
|
944
|
+
dispose() {
|
|
945
|
+
if (this._disposed) {
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
this._disposed = true;
|
|
949
|
+
this._listeners?.clear();
|
|
950
|
+
this._deliveryQueue?.clear(this);
|
|
951
|
+
}
|
|
952
|
+
fire(...event) {
|
|
953
|
+
if (!this._listeners || this._listeners.size === 0) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
if (this._listeners.size === 1) {
|
|
957
|
+
const listener = this._listeners.firstNode;
|
|
958
|
+
try {
|
|
959
|
+
listener.value.invoke(...event);
|
|
960
|
+
} catch (e) {
|
|
961
|
+
if (this._options?.onListenerError) {
|
|
962
|
+
this._options.onListenerError(e);
|
|
963
|
+
} else {
|
|
964
|
+
asyncUnexpectedError(e);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
this._deliveryQueue ?? (this._deliveryQueue = new EventDeliveryQueue(this._options?.onListenerError));
|
|
970
|
+
for (const listener of this._listeners) {
|
|
971
|
+
this._deliveryQueue.push(this, listener, event);
|
|
972
|
+
}
|
|
973
|
+
this._deliveryQueue.deliver();
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
// src/event/once.ts
|
|
978
|
+
function listenOnce(event) {
|
|
979
|
+
return (listener, thisArgs = null) => {
|
|
980
|
+
let didFire = false;
|
|
981
|
+
let result = void 0;
|
|
982
|
+
result = event((...args) => {
|
|
983
|
+
if (didFire) {
|
|
984
|
+
return;
|
|
985
|
+
} else if (result) {
|
|
986
|
+
result.dispose();
|
|
987
|
+
} else {
|
|
988
|
+
didFire = true;
|
|
989
|
+
}
|
|
990
|
+
return listener.call(thisArgs, ...args);
|
|
991
|
+
}, null);
|
|
992
|
+
if (didFire) {
|
|
993
|
+
result.dispose();
|
|
994
|
+
}
|
|
995
|
+
return result;
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// src/di/idle-value.ts
|
|
1000
|
+
var IdleValue = class {
|
|
1001
|
+
constructor(executor) {
|
|
1002
|
+
this._didRun = false;
|
|
1003
|
+
this._executor = () => {
|
|
1004
|
+
try {
|
|
1005
|
+
this._value = executor();
|
|
1006
|
+
} catch (err) {
|
|
1007
|
+
this._error = err;
|
|
1008
|
+
throw err;
|
|
1009
|
+
} finally {
|
|
1010
|
+
this._didRun = true;
|
|
1011
|
+
if (this._value && this._executorEmitter) {
|
|
1012
|
+
this._executorEmitter.fire();
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
this._handle = lvSchedulerCallback(() => this._executor(), {
|
|
1017
|
+
priorityLevel: 4 /* IdlePriority */
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
get value() {
|
|
1021
|
+
if (!this._didRun) {
|
|
1022
|
+
this._handle.dispose();
|
|
1023
|
+
this._executor();
|
|
1024
|
+
}
|
|
1025
|
+
if (this._error) {
|
|
1026
|
+
throw this._error;
|
|
1027
|
+
}
|
|
1028
|
+
return this._value;
|
|
1029
|
+
}
|
|
1030
|
+
get isInitialized() {
|
|
1031
|
+
return this._didRun;
|
|
1032
|
+
}
|
|
1033
|
+
get onExecutor() {
|
|
1034
|
+
if (!this._executorEmitter) {
|
|
1035
|
+
this._executorEmitter = new Emitter();
|
|
1036
|
+
}
|
|
1037
|
+
return this._executorEmitter.event;
|
|
1038
|
+
}
|
|
1039
|
+
dispose() {
|
|
1040
|
+
this._handle.dispose();
|
|
1041
|
+
}
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
// src/structure/graph.ts
|
|
1045
|
+
var Node = class {
|
|
1046
|
+
constructor(key, data) {
|
|
1047
|
+
this.key = key;
|
|
1048
|
+
this.data = data;
|
|
1049
|
+
this.incoming = /* @__PURE__ */ new Map();
|
|
1050
|
+
this.outgoing = /* @__PURE__ */ new Map();
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
var Graph = class {
|
|
1054
|
+
constructor(_hashFn) {
|
|
1055
|
+
this._hashFn = _hashFn;
|
|
1056
|
+
this._nodes = /* @__PURE__ */ new Map();
|
|
1057
|
+
}
|
|
1058
|
+
// 寻找所有的叶子节点
|
|
1059
|
+
leafs() {
|
|
1060
|
+
const ret = [];
|
|
1061
|
+
for (const node of this._nodes.values()) {
|
|
1062
|
+
if (node.outgoing.size === 0) {
|
|
1063
|
+
ret.push(node);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return ret;
|
|
1067
|
+
}
|
|
1068
|
+
// 插入一条边
|
|
1069
|
+
insertEdge(from, to) {
|
|
1070
|
+
const fromNode = this.lookupOrInsertNode(from);
|
|
1071
|
+
const toNode = this.lookupOrInsertNode(to);
|
|
1072
|
+
fromNode.outgoing.set(toNode.key, toNode);
|
|
1073
|
+
toNode.incoming.set(fromNode.key, fromNode);
|
|
1074
|
+
}
|
|
1075
|
+
// 移除某个节点
|
|
1076
|
+
removeNode(data) {
|
|
1077
|
+
const key = this._hashFn(data);
|
|
1078
|
+
this._nodes.delete(key);
|
|
1079
|
+
for (const node of this._nodes.values()) {
|
|
1080
|
+
node.outgoing.delete(key);
|
|
1081
|
+
node.incoming.delete(key);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
// 查找某个节点
|
|
1085
|
+
lookup(data) {
|
|
1086
|
+
return this._nodes.get(this._hashFn(data));
|
|
1087
|
+
}
|
|
1088
|
+
// 查找某个节点,不存在则插入
|
|
1089
|
+
lookupOrInsertNode(data) {
|
|
1090
|
+
const key = this._hashFn(data);
|
|
1091
|
+
let node = this._nodes.get(key);
|
|
1092
|
+
if (!node) {
|
|
1093
|
+
node = new Node(key, data);
|
|
1094
|
+
this._nodes.set(key, node);
|
|
1095
|
+
}
|
|
1096
|
+
return node;
|
|
1097
|
+
}
|
|
1098
|
+
isEmpty() {
|
|
1099
|
+
return this._nodes.size === 0;
|
|
1100
|
+
}
|
|
1101
|
+
toString() {
|
|
1102
|
+
const data = [];
|
|
1103
|
+
for (const [key, value] of this._nodes) {
|
|
1104
|
+
data.push(
|
|
1105
|
+
`${key}
|
|
1106
|
+
(-> incoming)[${[...value.incoming.keys()].join(", ")}]
|
|
1107
|
+
(outgoing ->)[${[
|
|
1108
|
+
...value.outgoing.keys()
|
|
1109
|
+
].join(",")}]
|
|
1110
|
+
`
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
return data.join("\n");
|
|
1114
|
+
}
|
|
1115
|
+
findCycleSlow() {
|
|
1116
|
+
for (const [id, node] of this._nodes) {
|
|
1117
|
+
const seen = /* @__PURE__ */ new Set([id]);
|
|
1118
|
+
const res = this._findCycle(node, seen);
|
|
1119
|
+
if (res) {
|
|
1120
|
+
return res;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return void 0;
|
|
1124
|
+
}
|
|
1125
|
+
_findCycle(node, seen) {
|
|
1126
|
+
for (const [id, outgoing] of node.outgoing) {
|
|
1127
|
+
if (seen.has(id)) {
|
|
1128
|
+
return [...seen, id].join(" -> ");
|
|
1129
|
+
}
|
|
1130
|
+
seen.add(id);
|
|
1131
|
+
const value = this._findCycle(outgoing, seen);
|
|
1132
|
+
if (value) {
|
|
1133
|
+
return value;
|
|
1134
|
+
}
|
|
1135
|
+
seen.delete(id);
|
|
1136
|
+
}
|
|
1137
|
+
return void 0;
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
|
|
1141
|
+
// src/di/service-collection.ts
|
|
1142
|
+
var ServiceCollection = class {
|
|
1143
|
+
constructor(options) {
|
|
1144
|
+
this._entries = /* @__PURE__ */ new Map();
|
|
1145
|
+
for (const [id, service] of options?.entries || []) {
|
|
1146
|
+
this.set(id, service);
|
|
1147
|
+
}
|
|
1148
|
+
if (options?.ownership) {
|
|
1149
|
+
this._ownership = options.ownership;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
get entries() {
|
|
1153
|
+
return this._entries;
|
|
1154
|
+
}
|
|
1155
|
+
get ownerships() {
|
|
1156
|
+
return this._ownership?.entries;
|
|
1157
|
+
}
|
|
1158
|
+
set(id, instanceOrDescriptor) {
|
|
1159
|
+
this._entries.set(id, instanceOrDescriptor);
|
|
1160
|
+
}
|
|
1161
|
+
has(id) {
|
|
1162
|
+
return this._entries.has(id);
|
|
1163
|
+
}
|
|
1164
|
+
get(id) {
|
|
1165
|
+
return this._entries.get(id);
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1169
|
+
// src/di/proxy-builder.ts
|
|
1170
|
+
function makeProxy(valueWrapper, ctor) {
|
|
1171
|
+
const wrapper = /* @__PURE__ */ Object.create(null);
|
|
1172
|
+
const result = new Proxy(wrapper, {
|
|
1173
|
+
get(target, key) {
|
|
1174
|
+
if (key in target) {
|
|
1175
|
+
return target[key];
|
|
1176
|
+
}
|
|
1177
|
+
const obj = valueWrapper.value;
|
|
1178
|
+
let prop = obj[key];
|
|
1179
|
+
if (typeof prop !== "function") {
|
|
1180
|
+
return prop;
|
|
1181
|
+
}
|
|
1182
|
+
prop = prop.bind(obj);
|
|
1183
|
+
target[key] = prop;
|
|
1184
|
+
return prop;
|
|
1185
|
+
},
|
|
1186
|
+
set(_target, p, value) {
|
|
1187
|
+
const obj = valueWrapper.value;
|
|
1188
|
+
obj[p] = value;
|
|
1189
|
+
return true;
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
wrapper.__originClass__ = ctor;
|
|
1193
|
+
listenOnce(valueWrapper.onExecutor)(() => {
|
|
1194
|
+
wrapper.__origin__ = valueWrapper.value;
|
|
1195
|
+
});
|
|
1196
|
+
return result;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// src/di/trace.ts
|
|
1200
|
+
var _Trace = class _Trace {
|
|
1201
|
+
constructor(type, name) {
|
|
1202
|
+
this._start = Date.now();
|
|
1203
|
+
this._dep = [];
|
|
1204
|
+
this._type = type;
|
|
1205
|
+
this._name = name;
|
|
1206
|
+
}
|
|
1207
|
+
static traceInvocation(_enableTracing, ctor) {
|
|
1208
|
+
return !_enableTracing ? _Trace._None : new _Trace(2 /* Invocation */, ctor.name || new Error().stack.split("\n").slice(3, 4).join("\n"));
|
|
1209
|
+
}
|
|
1210
|
+
static traceCreation(_enableTracing, ctor) {
|
|
1211
|
+
return !_enableTracing ? _Trace._None : new _Trace(1 /* Creation */, ctor.name);
|
|
1212
|
+
}
|
|
1213
|
+
branch(id, first) {
|
|
1214
|
+
const child = new _Trace(3 /* Branch */, id.toString());
|
|
1215
|
+
this._dep.push([id, first, child]);
|
|
1216
|
+
return child;
|
|
1217
|
+
}
|
|
1218
|
+
stop() {
|
|
1219
|
+
const dur = Date.now() - this._start;
|
|
1220
|
+
_Trace._totals += dur;
|
|
1221
|
+
let causedCreation = false;
|
|
1222
|
+
function printChild(n, trace) {
|
|
1223
|
+
const res = [];
|
|
1224
|
+
const prefix = new Array(n + 1).join(" ");
|
|
1225
|
+
for (const [id, first, child] of trace._dep) {
|
|
1226
|
+
if (first && child) {
|
|
1227
|
+
causedCreation = true;
|
|
1228
|
+
res.push(`${prefix}CREATES -> ${id}`);
|
|
1229
|
+
const nested = printChild(n + 1, child);
|
|
1230
|
+
if (nested) {
|
|
1231
|
+
res.push(nested);
|
|
1232
|
+
}
|
|
1233
|
+
} else {
|
|
1234
|
+
res.push(`${prefix}uses -> ${id}`);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
return res.join("\n");
|
|
1238
|
+
}
|
|
1239
|
+
const lines = [
|
|
1240
|
+
`${this._type === 1 /* Creation */ ? "CREATE" : "CALL"} ${this._name}`,
|
|
1241
|
+
`${printChild(1, this)}`,
|
|
1242
|
+
`DONE, took ${dur.toFixed(2)}ms (grand total ${_Trace._totals.toFixed(2)}ms)`
|
|
1243
|
+
];
|
|
1244
|
+
if (dur > 2 || causedCreation) {
|
|
1245
|
+
_Trace.all.add(lines.join("\n"));
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
_Trace.all = /* @__PURE__ */ new Set();
|
|
1250
|
+
_Trace._None = new class extends _Trace {
|
|
1251
|
+
constructor() {
|
|
1252
|
+
super(0 /* None */, null);
|
|
1253
|
+
}
|
|
1254
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
1255
|
+
stop() {
|
|
1256
|
+
}
|
|
1257
|
+
branch() {
|
|
1258
|
+
return this;
|
|
1259
|
+
}
|
|
1260
|
+
}();
|
|
1261
|
+
_Trace._totals = 0;
|
|
1262
|
+
var Trace = _Trace;
|
|
1263
|
+
|
|
1264
|
+
// src/di/instantiation-service.ts
|
|
1265
|
+
var _enableAllTracing = false;
|
|
1266
|
+
var CyclicDependencyError = class extends Error {
|
|
1267
|
+
constructor(graph) {
|
|
1268
|
+
super("cyclic dependency between services");
|
|
1269
|
+
this.message = graph.findCycleSlow() ?? `UNABLE to detect cycle, dumping graph:
|
|
1270
|
+
${graph.toString()}`;
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
var InstantiationService = class _InstantiationService {
|
|
1274
|
+
constructor(services = new ServiceCollection(), parent, enableTracing = _enableAllTracing) {
|
|
1275
|
+
this._childs = /* @__PURE__ */ new Set();
|
|
1276
|
+
// 记录当前正在创建的服务,防止循环依赖
|
|
1277
|
+
this._activeInstantiations = /* @__PURE__ */ new Set();
|
|
1278
|
+
this._emitter = null;
|
|
1279
|
+
this._services = services;
|
|
1280
|
+
this._services.set(IInstantiationService, this);
|
|
1281
|
+
this._parent = parent;
|
|
1282
|
+
if (this._parent) {
|
|
1283
|
+
this._parent._childs.add(this);
|
|
1284
|
+
}
|
|
1285
|
+
this._enableTracing = enableTracing;
|
|
1286
|
+
if (enableTracing) {
|
|
1287
|
+
this._globalGraph = parent?._globalGraph ?? new Graph((e) => e);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
get services() {
|
|
1291
|
+
return this._services;
|
|
1292
|
+
}
|
|
1293
|
+
// 仅限 Flow 调用
|
|
1294
|
+
get onError() {
|
|
1295
|
+
if (!this._emitter) {
|
|
1296
|
+
this._emitter = new Emitter();
|
|
1297
|
+
}
|
|
1298
|
+
return this._emitter.event;
|
|
1299
|
+
}
|
|
1300
|
+
// 创建子instantiationService
|
|
1301
|
+
createChild(services) {
|
|
1302
|
+
return new _InstantiationService(services, this, this._enableTracing);
|
|
1303
|
+
}
|
|
1304
|
+
// 提供通过instantiationService直接获取到内部服务的能力
|
|
1305
|
+
// 返回servicesAccessor这一视图类,并不暴露instantiationService内部接口
|
|
1306
|
+
invokeFunction(fn, ...args) {
|
|
1307
|
+
const _trace = Trace.traceInvocation(this._enableTracing, fn);
|
|
1308
|
+
let _done = false;
|
|
1309
|
+
try {
|
|
1310
|
+
const accessor = {
|
|
1311
|
+
get: (id) => {
|
|
1312
|
+
if (_done) {
|
|
1313
|
+
throw new Error("service accessor is only valid during the invocation of its target method");
|
|
1314
|
+
}
|
|
1315
|
+
const result = this._getOrCreateServiceInstance(id, _trace);
|
|
1316
|
+
if (!result) {
|
|
1317
|
+
this._handleError({
|
|
1318
|
+
errorType: "UnknownDependency" /* UnknownDependency */,
|
|
1319
|
+
issuer: "service-accessor",
|
|
1320
|
+
dependencyId: `${id}`,
|
|
1321
|
+
message: `[invokeFunction] unknown service '${id}'`
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
return result;
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
return fn(accessor, ...args);
|
|
1328
|
+
} finally {
|
|
1329
|
+
_done = true;
|
|
1330
|
+
_trace.stop();
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
createInstance(ctorOrDescriptor, ...rest) {
|
|
1334
|
+
let _trace, result;
|
|
1335
|
+
if (ctorOrDescriptor instanceof SyncDescriptor) {
|
|
1336
|
+
_trace = Trace.traceCreation(this._enableTracing, ctorOrDescriptor.ctor);
|
|
1337
|
+
result = this._createInstance(
|
|
1338
|
+
ctorOrDescriptor.ctor,
|
|
1339
|
+
ctorOrDescriptor.staticArguments.concat(rest),
|
|
1340
|
+
_trace
|
|
1341
|
+
);
|
|
1342
|
+
} else {
|
|
1343
|
+
_trace = Trace.traceCreation(this._enableTracing, ctorOrDescriptor);
|
|
1344
|
+
result = this._createInstance(ctorOrDescriptor, rest, _trace);
|
|
1345
|
+
}
|
|
1346
|
+
_trace.stop();
|
|
1347
|
+
return result;
|
|
1348
|
+
}
|
|
1349
|
+
dispose() {
|
|
1350
|
+
for (const child of this._childs) {
|
|
1351
|
+
child.dispose();
|
|
1352
|
+
}
|
|
1353
|
+
this._parent?._childs.delete(this);
|
|
1354
|
+
for (const [identifier, instanceOrDescriptor] of this._services.entries) {
|
|
1355
|
+
if (instanceOrDescriptor instanceof SyncDescriptor) {
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
if (instanceOrDescriptor === this) {
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
if (instanceOrDescriptor.__origin__ === this) {
|
|
1362
|
+
continue;
|
|
1363
|
+
}
|
|
1364
|
+
if (isDisposable(instanceOrDescriptor)) {
|
|
1365
|
+
const ownerShip = this._services.ownerships?.get(identifier);
|
|
1366
|
+
switch (ownerShip) {
|
|
1367
|
+
case 2 /* Reference */:
|
|
1368
|
+
break;
|
|
1369
|
+
case 1 /* Owned */:
|
|
1370
|
+
default:
|
|
1371
|
+
instanceOrDescriptor.dispose();
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
// 创建实例
|
|
1378
|
+
_createInstance(ctor, args = [], _trace) {
|
|
1379
|
+
const serviceDependencies = getServiceDependencies(ctor).sort((a, b) => a.index - b.index);
|
|
1380
|
+
const serviceArgs = [];
|
|
1381
|
+
for (const dependency of serviceDependencies) {
|
|
1382
|
+
const service = this._getOrCreateServiceInstance(dependency.id, _trace);
|
|
1383
|
+
if (!service) {
|
|
1384
|
+
this._handleError({
|
|
1385
|
+
errorType: "UnknownDependency" /* UnknownDependency */,
|
|
1386
|
+
issuer: `create-instance-${ctor.name}`,
|
|
1387
|
+
dependencyId: `${dependency.id}`,
|
|
1388
|
+
message: `[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
serviceArgs.push(service);
|
|
1392
|
+
}
|
|
1393
|
+
const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;
|
|
1394
|
+
if (args.length !== firstServiceArgPos) {
|
|
1395
|
+
Logger.trace(
|
|
1396
|
+
`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`
|
|
1397
|
+
);
|
|
1398
|
+
const delta = firstServiceArgPos - args.length;
|
|
1399
|
+
if (delta > 0) {
|
|
1400
|
+
args = args.concat(new Array(delta));
|
|
1401
|
+
} else {
|
|
1402
|
+
args = args.slice(0, firstServiceArgPos);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return Reflect.construct(ctor, args.concat(serviceArgs));
|
|
1406
|
+
}
|
|
1407
|
+
// 保存服务实例
|
|
1408
|
+
_setServiceInstance(id, instance) {
|
|
1409
|
+
if (this._services.get(id) instanceof SyncDescriptor) {
|
|
1410
|
+
this._services.set(id, instance);
|
|
1411
|
+
} else if (this._parent) {
|
|
1412
|
+
this._parent._setServiceInstance(id, instance);
|
|
1413
|
+
} else {
|
|
1414
|
+
throw new Error("illegalState - setting UNKNOWN service instance");
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
// 获取服务实例或者描述符
|
|
1418
|
+
_getServiceInstanceOrDescriptor(id) {
|
|
1419
|
+
const instanceOrDesc = this._services.get(id);
|
|
1420
|
+
if (!instanceOrDesc && this._parent) {
|
|
1421
|
+
return this._parent._getServiceInstanceOrDescriptor(id);
|
|
1422
|
+
} else {
|
|
1423
|
+
return instanceOrDesc;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
// 获取服务实例,没有的话就创建
|
|
1427
|
+
_getOrCreateServiceInstance(id, _trace) {
|
|
1428
|
+
if (this._globalGraph && this._globalGraphImplicitDependency) {
|
|
1429
|
+
this._globalGraph.insertEdge(this._globalGraphImplicitDependency, String(id));
|
|
1430
|
+
}
|
|
1431
|
+
const thing = this._getServiceInstanceOrDescriptor(id);
|
|
1432
|
+
if (thing instanceof SyncDescriptor) {
|
|
1433
|
+
return this._safeCreateAndCacheServiceInstance(id, thing, _trace.branch(id, true));
|
|
1434
|
+
} else {
|
|
1435
|
+
_trace.branch(id, false);
|
|
1436
|
+
return thing;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
// 安全的创建并且记录在缓存中
|
|
1440
|
+
_safeCreateAndCacheServiceInstance(id, desc, _trace) {
|
|
1441
|
+
if (this._activeInstantiations.has(id)) {
|
|
1442
|
+
throw new Error(`illegal state - RECURSIVELY instantiating service '${id}'`);
|
|
1443
|
+
}
|
|
1444
|
+
this._activeInstantiations.add(id);
|
|
1445
|
+
try {
|
|
1446
|
+
return this._createAndCacheServiceInstance(id, desc, _trace);
|
|
1447
|
+
} finally {
|
|
1448
|
+
this._activeInstantiations.delete(id);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
// 非安全创建并记录在缓存中
|
|
1452
|
+
// 核心方法,服务创建的最基础流程
|
|
1453
|
+
_createAndCacheServiceInstance(id, desc, _trace) {
|
|
1454
|
+
const graph = new Graph((data) => data.id.toString());
|
|
1455
|
+
let cycleCount = 0;
|
|
1456
|
+
const stack = [{ id, desc, _trace }];
|
|
1457
|
+
while (stack.length) {
|
|
1458
|
+
const item = stack.pop();
|
|
1459
|
+
graph.lookupOrInsertNode(item);
|
|
1460
|
+
if (cycleCount++ > 1e3) {
|
|
1461
|
+
throw new CyclicDependencyError(graph);
|
|
1462
|
+
}
|
|
1463
|
+
for (const dependency of getServiceDependencies(item.desc.ctor)) {
|
|
1464
|
+
const instanceOrDesc = this._getServiceInstanceOrDescriptor(dependency.id);
|
|
1465
|
+
if (!instanceOrDesc) {
|
|
1466
|
+
this._handleError({
|
|
1467
|
+
errorType: "UnknownDependency" /* UnknownDependency */,
|
|
1468
|
+
issuer: `create-service-${id}`,
|
|
1469
|
+
dependencyId: `${dependency.id}`,
|
|
1470
|
+
message: `[createInstance] ${id} depends on ${dependency.id} which is NOT registered.`
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
this._globalGraph?.insertEdge(String(item.id), String(dependency.id));
|
|
1474
|
+
if (instanceOrDesc instanceof SyncDescriptor) {
|
|
1475
|
+
const d = {
|
|
1476
|
+
id: dependency.id,
|
|
1477
|
+
desc: instanceOrDesc,
|
|
1478
|
+
_trace: item._trace.branch(dependency.id, true)
|
|
1479
|
+
};
|
|
1480
|
+
graph.insertEdge(item, d);
|
|
1481
|
+
stack.push(d);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
while (true) {
|
|
1486
|
+
const leafs = graph.leafs();
|
|
1487
|
+
if (leafs.length === 0) {
|
|
1488
|
+
if (!graph.isEmpty()) {
|
|
1489
|
+
throw new CyclicDependencyError(graph);
|
|
1490
|
+
}
|
|
1491
|
+
break;
|
|
1492
|
+
}
|
|
1493
|
+
for (const { data } of leafs) {
|
|
1494
|
+
const instanceOrDesc = this._getServiceInstanceOrDescriptor(data.id);
|
|
1495
|
+
if (instanceOrDesc instanceof SyncDescriptor) {
|
|
1496
|
+
const instance = this._createServiceInstanceWithOwner(
|
|
1497
|
+
data.id,
|
|
1498
|
+
data.desc.ctor,
|
|
1499
|
+
data.desc.staticArguments,
|
|
1500
|
+
data.desc.supportsDelayedInstantiation,
|
|
1501
|
+
data._trace
|
|
1502
|
+
);
|
|
1503
|
+
this._setServiceInstance(data.id, instance);
|
|
1504
|
+
}
|
|
1505
|
+
graph.removeNode(data);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return this._getServiceInstanceOrDescriptor(id);
|
|
1509
|
+
}
|
|
1510
|
+
// 创建服务实例(会判断在哪层instantiation中判断)
|
|
1511
|
+
_createServiceInstanceWithOwner(id, ctor, args = [], supportsDelayedInstantiation, _trace) {
|
|
1512
|
+
if (this._services.get(id) instanceof SyncDescriptor) {
|
|
1513
|
+
return this._createServiceInstance(id, ctor, args, supportsDelayedInstantiation, _trace);
|
|
1514
|
+
} else if (this._parent) {
|
|
1515
|
+
return this._parent._createServiceInstanceWithOwner(
|
|
1516
|
+
id,
|
|
1517
|
+
ctor,
|
|
1518
|
+
args,
|
|
1519
|
+
supportsDelayedInstantiation,
|
|
1520
|
+
_trace
|
|
1521
|
+
);
|
|
1522
|
+
} else {
|
|
1523
|
+
throw new Error(`illegalState - creating UNKNOWN service instance ${ctor.name}`);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
// 准备创建服务实例
|
|
1527
|
+
_createServiceInstance(id, ctor, args = [], supportsDelayedInstantiation, _trace) {
|
|
1528
|
+
if (!supportsDelayedInstantiation) {
|
|
1529
|
+
return this._createService(ctor, args, _trace);
|
|
1530
|
+
}
|
|
1531
|
+
const idle = new IdleValue(() => this._createService(ctor, args, _trace));
|
|
1532
|
+
return makeProxy(idle, ctor);
|
|
1533
|
+
}
|
|
1534
|
+
// 创建服务
|
|
1535
|
+
_createService(ctor, args = [], _trace) {
|
|
1536
|
+
const service = this._createInstance(ctor, args, _trace);
|
|
1537
|
+
if (isDisposable(service)) ;
|
|
1538
|
+
return service;
|
|
1539
|
+
}
|
|
1540
|
+
// 处理错误
|
|
1541
|
+
_handleError(errorData) {
|
|
1542
|
+
let topInstantiationService = this;
|
|
1543
|
+
while (topInstantiationService._parent) {
|
|
1544
|
+
topInstantiationService = topInstantiationService._parent;
|
|
1545
|
+
}
|
|
1546
|
+
if (topInstantiationService._emitter) {
|
|
1547
|
+
topInstantiationService._emitter.fire(errorData);
|
|
1548
|
+
}
|
|
1549
|
+
throw new Error(errorData.message);
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
|
|
1553
|
+
// src/services/dynamic-dependency/dynamic-dependency-service.interface.ts
|
|
1554
|
+
var IDynamicDependencyService = createDecorator(
|
|
1555
|
+
"dynamic-dependency-service"
|
|
1556
|
+
);
|
|
1557
|
+
|
|
1558
|
+
// src/services/dynamic-dependency/dynamic-dependency-service.ts
|
|
1559
|
+
var DynamicDependencyService = class extends InstantiationService {
|
|
1560
|
+
constructor(_containerService) {
|
|
1561
|
+
const collection = new ServiceCollection();
|
|
1562
|
+
super(collection, _containerService);
|
|
1563
|
+
this._servicesCollection = collection;
|
|
1564
|
+
}
|
|
1565
|
+
register(id, ctorOrDescriptor) {
|
|
1566
|
+
if (this._servicesCollection.has(id)) {
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
if (!(ctorOrDescriptor instanceof SyncDescriptor)) {
|
|
1570
|
+
ctorOrDescriptor = new SyncDescriptor(ctorOrDescriptor, []);
|
|
1571
|
+
}
|
|
1572
|
+
this._servicesCollection.set(id, ctorOrDescriptor);
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
DynamicDependencyService = __decorateClass([
|
|
1576
|
+
__decorateParam(0, IInstantiationService)
|
|
1577
|
+
], DynamicDependencyService);
|
|
1578
|
+
|
|
1579
|
+
export { DynamicDependencyService, IDynamicDependencyService };
|
|
1580
|
+
//# sourceMappingURL=index.js.map
|
|
1581
|
+
//# sourceMappingURL=index.js.map
|