@zk-tech/bedrock 0.0.1
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 +24 -0
- package/dist/array/index.cjs +22 -0
- package/dist/array/index.cjs.map +1 -0
- package/dist/array/index.d.cts +13 -0
- package/dist/array/index.d.ts +13 -0
- package/dist/array/index.js +19 -0
- package/dist/array/index.js.map +1 -0
- package/dist/assert/index.cjs +29 -0
- package/dist/assert/index.cjs.map +1 -0
- package/dist/assert/index.d.cts +25 -0
- package/dist/assert/index.d.ts +25 -0
- package/dist/assert/index.js +24 -0
- package/dist/assert/index.js.map +1 -0
- package/dist/async/index.cjs +746 -0
- package/dist/async/index.cjs.map +1 -0
- package/dist/async/index.d.cts +47 -0
- package/dist/async/index.d.ts +47 -0
- package/dist/async/index.js +738 -0
- package/dist/async/index.js.map +1 -0
- package/dist/barrier-316Xonfd.d.cts +18 -0
- package/dist/barrier-316Xonfd.d.ts +18 -0
- package/dist/byte/index.cjs +59 -0
- package/dist/byte/index.cjs.map +1 -0
- package/dist/byte/index.d.cts +12 -0
- package/dist/byte/index.d.ts +12 -0
- package/dist/byte/index.js +49 -0
- package/dist/byte/index.js.map +1 -0
- package/dist/cache/index.cjs +418 -0
- package/dist/cache/index.cjs.map +1 -0
- package/dist/cache/index.d.cts +40 -0
- package/dist/cache/index.d.ts +40 -0
- package/dist/cache/index.js +415 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cancellation-BIIv2UJm.d.cts +25 -0
- package/dist/cancellation-ClqPPsV1.d.ts +25 -0
- package/dist/context/index.cjs +59 -0
- package/dist/context/index.cjs.map +1 -0
- package/dist/context/index.d.cts +33 -0
- package/dist/context/index.d.ts +33 -0
- package/dist/context/index.js +51 -0
- package/dist/context/index.js.map +1 -0
- package/dist/di/index.cjs +1965 -0
- package/dist/di/index.cjs.map +1 -0
- package/dist/di/index.d.cts +140 -0
- package/dist/di/index.d.ts +140 -0
- package/dist/di/index.js +1949 -0
- package/dist/di/index.js.map +1 -0
- package/dist/disposable-t-B15Nu57y.d.ts +93 -0
- package/dist/disposable-t-CVsiyHPL.d.cts +93 -0
- package/dist/dispose/index.cjs +356 -0
- package/dist/dispose/index.cjs.map +1 -0
- package/dist/dispose/index.d.cts +26 -0
- package/dist/dispose/index.d.ts +26 -0
- package/dist/dispose/index.js +340 -0
- package/dist/dispose/index.js.map +1 -0
- package/dist/dispose-base-CAeXDpjg.d.cts +6 -0
- package/dist/dispose-base-CAeXDpjg.d.ts +6 -0
- package/dist/emitter-CAfCtSTg.d.cts +35 -0
- package/dist/emitter-DeM5mlEm.d.ts +35 -0
- package/dist/error/index.cjs +145 -0
- package/dist/error/index.cjs.map +1 -0
- package/dist/error/index.d.cts +45 -0
- package/dist/error/index.d.ts +45 -0
- package/dist/error/index.js +126 -0
- package/dist/error/index.js.map +1 -0
- package/dist/error-base-B4zaiJ5m.d.cts +32 -0
- package/dist/error-base-B4zaiJ5m.d.ts +32 -0
- package/dist/event/index.cjs +550 -0
- package/dist/event/index.cjs.map +1 -0
- package/dist/event/index.d.cts +139 -0
- package/dist/event/index.d.ts +139 -0
- package/dist/event/index.js +538 -0
- package/dist/event/index.js.map +1 -0
- package/dist/function/index.cjs +132 -0
- package/dist/function/index.cjs.map +1 -0
- package/dist/function/index.d.cts +26 -0
- package/dist/function/index.d.ts +26 -0
- package/dist/function/index.js +129 -0
- package/dist/function/index.js.map +1 -0
- package/dist/graph-BGbNOniY.d.cts +23 -0
- package/dist/graph-BGbNOniY.d.ts +23 -0
- package/dist/hash/index.cjs +54 -0
- package/dist/hash/index.cjs.map +1 -0
- package/dist/hash/index.d.cts +5 -0
- package/dist/hash/index.d.ts +5 -0
- package/dist/hash/index.js +50 -0
- package/dist/hash/index.js.map +1 -0
- package/dist/instantiation-service.interface-CVFMBUUD.d.cts +78 -0
- package/dist/instantiation-service.interface-CVFMBUUD.d.ts +78 -0
- package/dist/json/index.cjs +28 -0
- package/dist/json/index.cjs.map +1 -0
- package/dist/json/index.d.cts +8 -0
- package/dist/json/index.d.ts +8 -0
- package/dist/json/index.js +26 -0
- package/dist/json/index.js.map +1 -0
- package/dist/launch/index.cjs +213 -0
- package/dist/launch/index.cjs.map +1 -0
- package/dist/launch/index.d.cts +46 -0
- package/dist/launch/index.d.ts +46 -0
- package/dist/launch/index.js +211 -0
- package/dist/launch/index.js.map +1 -0
- package/dist/linked-list-CUkue5DZ.d.cts +24 -0
- package/dist/linked-list-CUkue5DZ.d.ts +24 -0
- package/dist/lock/index.cjs +662 -0
- package/dist/lock/index.cjs.map +1 -0
- package/dist/lock/index.d.cts +145 -0
- package/dist/lock/index.d.ts +145 -0
- package/dist/lock/index.js +656 -0
- package/dist/lock/index.js.map +1 -0
- package/dist/lodash-es/index.cjs +14 -0
- package/dist/lodash-es/index.cjs.map +1 -0
- package/dist/lodash-es/index.d.cts +1 -0
- package/dist/lodash-es/index.d.ts +1 -0
- package/dist/lodash-es/index.js +3 -0
- package/dist/lodash-es/index.js.map +1 -0
- package/dist/math/index.cjs +161 -0
- package/dist/math/index.cjs.map +1 -0
- package/dist/math/index.d.cts +76 -0
- package/dist/math/index.d.ts +76 -0
- package/dist/math/index.js +156 -0
- package/dist/math/index.js.map +1 -0
- package/dist/network/index.cjs +91 -0
- package/dist/network/index.cjs.map +1 -0
- package/dist/network/index.d.cts +62 -0
- package/dist/network/index.d.ts +62 -0
- package/dist/network/index.js +82 -0
- package/dist/network/index.js.map +1 -0
- package/dist/objects/index.cjs +80 -0
- package/dist/objects/index.cjs.map +1 -0
- package/dist/objects/index.d.cts +11 -0
- package/dist/objects/index.d.ts +11 -0
- package/dist/objects/index.js +77 -0
- package/dist/objects/index.js.map +1 -0
- package/dist/platform/index.cjs +62 -0
- package/dist/platform/index.cjs.map +1 -0
- package/dist/platform/index.d.cts +21 -0
- package/dist/platform/index.d.ts +21 -0
- package/dist/platform/index.js +48 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/promise/index.cjs +639 -0
- package/dist/promise/index.cjs.map +1 -0
- package/dist/promise/index.d.cts +63 -0
- package/dist/promise/index.d.ts +63 -0
- package/dist/promise/index.js +633 -0
- package/dist/promise/index.js.map +1 -0
- package/dist/scheduler/index.cjs +599 -0
- package/dist/scheduler/index.cjs.map +1 -0
- package/dist/scheduler/index.d.cts +57 -0
- package/dist/scheduler/index.d.ts +57 -0
- package/dist/scheduler/index.js +594 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/sprintf/index.cjs +101 -0
- package/dist/sprintf/index.cjs.map +1 -0
- package/dist/sprintf/index.d.cts +3 -0
- package/dist/sprintf/index.d.ts +3 -0
- package/dist/sprintf/index.js +99 -0
- package/dist/sprintf/index.js.map +1 -0
- package/dist/structure/index.cjs +300 -0
- package/dist/structure/index.cjs.map +1 -0
- package/dist/structure/index.d.cts +21 -0
- package/dist/structure/index.d.ts +21 -0
- package/dist/structure/index.js +296 -0
- package/dist/structure/index.js.map +1 -0
- package/dist/type/index.cjs +4 -0
- package/dist/type/index.cjs.map +1 -0
- package/dist/type/index.d.cts +20 -0
- package/dist/type/index.d.ts +20 -0
- package/dist/type/index.js +3 -0
- package/dist/type/index.js.map +1 -0
- package/dist/undo-redo-stack/index.cjs +545 -0
- package/dist/undo-redo-stack/index.cjs.map +1 -0
- package/dist/undo-redo-stack/index.d.cts +130 -0
- package/dist/undo-redo-stack/index.d.ts +130 -0
- package/dist/undo-redo-stack/index.js +542 -0
- package/dist/undo-redo-stack/index.js.map +1 -0
- package/dist/uuid/index.cjs +67 -0
- package/dist/uuid/index.cjs.map +1 -0
- package/dist/uuid/index.d.cts +17 -0
- package/dist/uuid/index.d.ts +17 -0
- package/dist/uuid/index.js +61 -0
- package/dist/uuid/index.js.map +1 -0
- package/dist/worker/index.cjs +271 -0
- package/dist/worker/index.cjs.map +1 -0
- package/dist/worker/index.d.cts +66 -0
- package/dist/worker/index.d.ts +66 -0
- package/dist/worker/index.js +267 -0
- package/dist/worker/index.js.map +1 -0
- package/package.json +285 -0
- package/src/_internal/logger.ts +59 -0
- package/src/array/array.test.ts +35 -0
- package/src/array/array.ts +25 -0
- package/src/array/index.ts +1 -0
- package/src/assert/assert.test.ts +86 -0
- package/src/assert/assert.ts +42 -0
- package/src/assert/index.ts +2 -0
- package/src/async/barrier.test.ts +90 -0
- package/src/async/barrier.ts +58 -0
- package/src/async/cancellation.test.ts +85 -0
- package/src/async/cancellation.ts +193 -0
- package/src/async/index.ts +18 -0
- package/src/async/queue/queue.test.ts +70 -0
- package/src/async/queue/queue.ts +56 -0
- package/src/async/queue/task.test.ts +155 -0
- package/src/async/queue/task.ts +67 -0
- package/src/async/utils.test.ts +28 -0
- package/src/async/utils.ts +8 -0
- package/src/async/wait.ts +9 -0
- package/src/byte/format.test.ts +64 -0
- package/src/byte/format.ts +44 -0
- package/src/byte/index.ts +2 -0
- package/src/byte/node_modules/.vitest/results.json +1 -0
- package/src/byte/var.ts +11 -0
- package/src/cache/index.ts +2 -0
- package/src/cache/lru-with-timeout.test.ts +88 -0
- package/src/cache/lru-with-timeout.ts +85 -0
- package/src/cache/lru.test.ts +56 -0
- package/src/cache/lru.ts +59 -0
- package/src/context/context.test.ts +17 -0
- package/src/context/context.ts +60 -0
- package/src/context/index.ts +8 -0
- package/src/di/base.ts +73 -0
- package/src/di/container-service.test.ts +179 -0
- package/src/di/context.web.tsx +41 -0
- package/src/di/descriptor.ts +31 -0
- package/src/di/idle-value.test.ts +73 -0
- package/src/di/idle-value.ts +63 -0
- package/src/di/index.common.ts +32 -0
- package/src/di/index.ts +2 -0
- package/src/di/instantiation-service.interface.ts +46 -0
- package/src/di/instantiation-service.test.ts +337 -0
- package/src/di/instantiation-service.ts +468 -0
- package/src/di/lazy/foo.mock.ts +28 -0
- package/src/di/lazy/idle-load.ts +39 -0
- package/src/di/lazy/index.ts +4 -0
- package/src/di/lazy/lazy-service.test.ts +65 -0
- package/src/di/lazy/lazy-service.ts +71 -0
- package/src/di/lazy/type.ts +5 -0
- package/src/di/node_modules/.vitest/results.json +1 -0
- package/src/di/proxy-builder.test.ts +45 -0
- package/src/di/proxy-builder.ts +38 -0
- package/src/di/service-collection.test.ts +27 -0
- package/src/di/service-collection.ts +46 -0
- package/src/di/service-ownership-collection.test.ts +39 -0
- package/src/di/service-ownership-collection.ts +38 -0
- package/src/di/service-registry.test.ts +66 -0
- package/src/di/service-registry.ts +99 -0
- package/src/di/trace.ts +85 -0
- package/src/dispose/disposable-store.test.ts +57 -0
- package/src/dispose/disposable-store.ts +80 -0
- package/src/dispose/disposable-t.test.ts +123 -0
- package/src/dispose/disposable-t.ts +238 -0
- package/src/dispose/disposable-utils.test.ts +15 -0
- package/src/dispose/disposable-utils.ts +28 -0
- package/src/dispose/dispose-base.ts +9 -0
- package/src/dispose/index.ts +34 -0
- package/src/dispose/logger.test.ts +65 -0
- package/src/dispose/logger.ts +39 -0
- package/src/dispose/timer.test.ts +30 -0
- package/src/dispose/timer.ts +16 -0
- package/src/dispose/tracker.test.ts +51 -0
- package/src/dispose/tracker.ts +105 -0
- package/src/error/error-base.ts +45 -0
- package/src/error/error-code.ts +39 -0
- package/src/error/error-const.test.ts +30 -0
- package/src/error/error-const.ts +16 -0
- package/src/error/error-or.test.ts +44 -0
- package/src/error/error-or.ts +2 -0
- package/src/error/error-t.test.ts +116 -0
- package/src/error/error-t.ts +100 -0
- package/src/error/index.ts +24 -0
- package/src/error/node_modules/.vitest/results.json +1 -0
- package/src/event/disposable-linked-list.ts +29 -0
- package/src/event/emitter.test.ts +191 -0
- package/src/event/emitter.ts +162 -0
- package/src/event/error-handler.ts +22 -0
- package/src/event/index.ts +34 -0
- package/src/event/once.ts +29 -0
- package/src/event/phase-emitter.test.ts +212 -0
- package/src/event/phase-emitter.ts +209 -0
- package/src/event/shortcut-event-utils.ts +33 -0
- package/src/event/utils.ts +6 -0
- package/src/event/when.ts +40 -0
- package/src/function/debounce.test.ts +274 -0
- package/src/function/debounce.ts +168 -0
- package/src/function/index.ts +2 -0
- package/src/function/node_modules/.vitest/results.json +1 -0
- package/src/function/throttle.test.ts +179 -0
- package/src/function/throttle.ts +26 -0
- package/src/hash/hash-t.test.ts +100 -0
- package/src/hash/hash-t.ts +51 -0
- package/src/hash/index.ts +3 -0
- package/src/json/index.ts +1 -0
- package/src/json/node_modules/.vitest/results.json +1 -0
- package/src/json/parse.ts +19 -0
- package/src/launch/abstract-job.ts +45 -0
- package/src/launch/cost-recorder.ts +22 -0
- package/src/launch/index.ts +2 -0
- package/src/launch/job-scheduler.test.ts +122 -0
- package/src/launch/job-scheduler.ts +118 -0
- package/src/launch/node_modules/.vitest/deps/_metadata.json +8 -0
- package/src/launch/node_modules/.vitest/deps/package.json +3 -0
- package/src/launch/node_modules/.vitest/results.json +1 -0
- package/src/lock/README.md +11 -0
- package/src/lock/capability.test.ts +110 -0
- package/src/lock/capability.ts +89 -0
- package/src/lock/index.ts +15 -0
- package/src/lock/node_modules/.vitest/results.json +1 -0
- package/src/lock/semaphore.ts +21 -0
- package/src/lock/shared-mutex.test.ts +537 -0
- package/src/lock/shared-mutex.ts +242 -0
- package/src/lock/utils.test.ts +165 -0
- package/src/lock/utils.ts +135 -0
- package/src/lodash-es/index.ts +1 -0
- package/src/math/degree.ts +16 -0
- package/src/math/index.ts +7 -0
- package/src/math/math.test.ts +40 -0
- package/src/math/math.ts +64 -0
- package/src/math/node_modules/.vitest/results.json +1 -0
- package/src/math/vector.test.ts +73 -0
- package/src/math/vector.ts +114 -0
- package/src/network/client.interface.ts +104 -0
- package/src/network/client.web.ts +24 -0
- package/src/network/index.common.ts +10 -0
- package/src/network/index.ts +2 -0
- package/src/network/plugins/retry.ts +98 -0
- package/src/objects/deep-clone.test.ts +40 -0
- package/src/objects/deep-clone.ts +13 -0
- package/src/objects/deep-equal.test.ts +86 -0
- package/src/objects/deep-equal.ts +60 -0
- package/src/objects/index.ts +4 -0
- package/src/platform/index.ts +64 -0
- package/src/promise/index.ts +16 -0
- package/src/promise/promise.test.ts +254 -0
- package/src/promise/promise.ts +212 -0
- package/src/scheduler/callback-token.ts +31 -0
- package/src/scheduler/core/actuator-args.test.ts +47 -0
- package/src/scheduler/core/actuator.test.ts +82 -0
- package/src/scheduler/core/actuator.ts +58 -0
- package/src/scheduler/core/chunk-scheduler.test.ts +54 -0
- package/src/scheduler/core/chunk-scheduler.ts +28 -0
- package/src/scheduler/core/node_modules/.vitest/results.json +1 -0
- package/src/scheduler/core/scheduler.test.ts +328 -0
- package/src/scheduler/core/scheduler.ts +172 -0
- package/src/scheduler/core/task-queue.test.ts +78 -0
- package/src/scheduler/core/task-queue.ts +44 -0
- package/src/scheduler/core/task.test.ts +34 -0
- package/src/scheduler/core/task.ts +52 -0
- package/src/scheduler/core/utils.ts +48 -0
- package/src/scheduler/executor/abstract-executor.test.ts +44 -0
- package/src/scheduler/executor/abstract-executor.ts +38 -0
- package/src/scheduler/executor/executor.interface.ts +39 -0
- package/src/scheduler/executor/idle-callback-executor.test.ts +70 -0
- package/src/scheduler/executor/idle-callback-executor.ts +98 -0
- package/src/scheduler/executor/make-executor.ts +18 -0
- package/src/scheduler/executor/post-message-executor.test.ts +66 -0
- package/src/scheduler/executor/post-message-executor.ts +52 -0
- package/src/scheduler/index.ts +15 -0
- package/src/scheduler/lv-scheduler-callback.ts +19 -0
- package/src/scheduler/lv-scheduler-config.ts +17 -0
- package/src/scheduler/type.ts +48 -0
- package/src/sprintf/index.ts +2 -0
- package/src/sprintf/sprintf.test.ts +95 -0
- package/src/sprintf/sprintf.ts +97 -0
- package/src/structure/graph.test.ts +181 -0
- package/src/structure/graph.ts +105 -0
- package/src/structure/index.ts +8 -0
- package/src/structure/linked-list.test.ts +74 -0
- package/src/structure/linked-list.ts +145 -0
- package/src/structure/min-heap.test.ts +71 -0
- package/src/structure/min-heap.ts +91 -0
- package/src/type/REAME.md +2 -0
- package/src/type/distributive-omit.interface.ts +4 -0
- package/src/type/index.ts +3 -0
- package/src/type/object-key-paths.interface.ts +40 -0
- package/src/undo-redo-stack/README.md +61 -0
- package/src/undo-redo-stack/action-stack.test.ts +330 -0
- package/src/undo-redo-stack/action-stack.ts +150 -0
- package/src/undo-redo-stack/element.ts +4 -0
- package/src/undo-redo-stack/index.ts +7 -0
- package/src/undo-redo-stack/state-stack.test.ts +118 -0
- package/src/undo-redo-stack/state-stack.ts +133 -0
- package/src/uuid/index.ts +7 -0
- package/src/uuid/uuid.ts +86 -0
- package/src/worker/cors-worker.ts +38 -0
- package/src/worker/index.ts +4 -0
- package/src/worker/node_modules/.vitest/results.json +1 -0
- package/src/worker/promise-worker-main-thread.test.ts +91 -0
- package/src/worker/promise-worker-main-thread.ts +76 -0
- package/src/worker/promise-worker-worker-thread.ts +64 -0
- package/src/worker/promise-worker.interface.ts +15 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { makeSafeDisposable, makeTransferDisposable } from './disposable-utils';
|
|
2
|
+
import {
|
|
3
|
+
Disposable,
|
|
4
|
+
MutableDisposable,
|
|
5
|
+
RefCountedDisposable,
|
|
6
|
+
SafeDisposable,
|
|
7
|
+
TransferDisposable,
|
|
8
|
+
} from './disposable-t';
|
|
9
|
+
import type { IDisposable } from './dispose-base';
|
|
10
|
+
|
|
11
|
+
class Bar extends Disposable {
|
|
12
|
+
constructor(mockFunc: () => void) {
|
|
13
|
+
super();
|
|
14
|
+
this._register(makeSafeDisposable(mockFunc));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class Foo extends Disposable {
|
|
19
|
+
constructor(mockFunc: () => void) {
|
|
20
|
+
super();
|
|
21
|
+
this._register(makeSafeDisposable(mockFunc));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class Test extends Disposable {
|
|
26
|
+
constructor(value: IDisposable) {
|
|
27
|
+
super();
|
|
28
|
+
this._register(value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('mutable disposable', () => {
|
|
33
|
+
it('set value', () => {
|
|
34
|
+
const barMock = vi.fn();
|
|
35
|
+
const fooMock = vi.fn();
|
|
36
|
+
const mutable = new MutableDisposable();
|
|
37
|
+
mutable.value = new Bar(barMock);
|
|
38
|
+
mutable.value = new Foo(barMock);
|
|
39
|
+
expect(barMock).toHaveBeenCalled();
|
|
40
|
+
expect(fooMock).not.toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('clear', () => {
|
|
44
|
+
const barMock = vi.fn();
|
|
45
|
+
const mutable = new MutableDisposable(new Bar(barMock));
|
|
46
|
+
mutable.clear();
|
|
47
|
+
expect(barMock).toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('release', () => {
|
|
51
|
+
const barMock = vi.fn();
|
|
52
|
+
const fooMock = vi.fn();
|
|
53
|
+
const mutable = new MutableDisposable();
|
|
54
|
+
mutable.value = new Bar(barMock);
|
|
55
|
+
mutable.release();
|
|
56
|
+
mutable.value = new Foo(barMock);
|
|
57
|
+
// 因为调用的是release,所以没有触发dispose
|
|
58
|
+
expect(barMock).not.toHaveBeenCalled();
|
|
59
|
+
expect(fooMock).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('dispose', () => {
|
|
63
|
+
const barMock = vi.fn();
|
|
64
|
+
const mutable = new MutableDisposable();
|
|
65
|
+
mutable.value = new Bar(barMock);
|
|
66
|
+
mutable.dispose();
|
|
67
|
+
expect(barMock).toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('safe disposable', () => {
|
|
72
|
+
it('dispose', () => {
|
|
73
|
+
const barMock = vi.fn();
|
|
74
|
+
const safe = new SafeDisposable(new Bar(barMock));
|
|
75
|
+
safe.dispose();
|
|
76
|
+
safe.dispose();
|
|
77
|
+
expect(barMock).toHaveBeenCalledTimes(1);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('RefCountedDisposable', () => {
|
|
82
|
+
it('test', () => {
|
|
83
|
+
const fnMock = vi.fn();
|
|
84
|
+
const disposable = makeSafeDisposable(fnMock);
|
|
85
|
+
const refCounted = new RefCountedDisposable(new Test(disposable));
|
|
86
|
+
refCounted.acquire();
|
|
87
|
+
|
|
88
|
+
refCounted.release();
|
|
89
|
+
expect(fnMock).toHaveBeenCalledTimes(0);
|
|
90
|
+
refCounted.dispose();
|
|
91
|
+
expect(fnMock).toHaveBeenCalledTimes(1);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe('TransferDisposable', () => {
|
|
96
|
+
class FooInternal implements IDisposable {
|
|
97
|
+
public count = 0;
|
|
98
|
+
|
|
99
|
+
dispose() {
|
|
100
|
+
this.count++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class BarInternal implements IDisposable {
|
|
105
|
+
private readonly _foo: FooInternal;
|
|
106
|
+
|
|
107
|
+
constructor(foo: TransferDisposable<FooInternal>) {
|
|
108
|
+
this._foo = foo.release();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
dispose() {
|
|
112
|
+
this._foo.dispose();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
it('transfer', () => {
|
|
117
|
+
const foo = new FooInternal();
|
|
118
|
+
const bar = new BarInternal(makeTransferDisposable(foo));
|
|
119
|
+
|
|
120
|
+
bar.dispose();
|
|
121
|
+
expect(foo.count).toBe(1);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { Logger } from '@/_internal/logger';
|
|
2
|
+
import { lvAssertNotNil } from '@/assert';
|
|
3
|
+
import { DisposableStore } from './disposable-store';
|
|
4
|
+
import type { IDisposable } from './dispose-base';
|
|
5
|
+
import { BRANCH_DISPOSE } from './logger';
|
|
6
|
+
import { MARK_AS_DISPOSED, SET_PARENT_OF_DISPOSABLE, TRACK_DISPOSABLE } from './tracker';
|
|
7
|
+
|
|
8
|
+
//
|
|
9
|
+
// Disposable基类
|
|
10
|
+
//
|
|
11
|
+
// 自动添加DisposableStore,提供默认的dispose和register方法
|
|
12
|
+
//
|
|
13
|
+
export abstract class Disposable implements IDisposable {
|
|
14
|
+
protected readonly _store = new DisposableStore();
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
TRACK_DISPOSABLE(this);
|
|
18
|
+
SET_PARENT_OF_DISPOSABLE(this._store, this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 销毁该节点和所有的子节点
|
|
22
|
+
dispose(): void {
|
|
23
|
+
MARK_AS_DISPOSED(this);
|
|
24
|
+
BRANCH_DISPOSE(this.constructor.name, this._store.constructor.name);
|
|
25
|
+
|
|
26
|
+
this._store.dispose();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 挂载子节点
|
|
30
|
+
protected _register<T extends IDisposable>(o: T): T {
|
|
31
|
+
if ((o as unknown as Disposable) === this) {
|
|
32
|
+
throw new Error('Cannot register a disposable on itself!');
|
|
33
|
+
}
|
|
34
|
+
return this._store.add(o);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 容器类
|
|
40
|
+
* 提供一个容器,容器内部的IDisposable对象可以切换更新,每次更新的时候,旧的IDisposable对象会自动进行dispose
|
|
41
|
+
*
|
|
42
|
+
* 使用方式:
|
|
43
|
+
* class Foo {
|
|
44
|
+
* private readonly _barRef: MutableDisposable;
|
|
45
|
+
*
|
|
46
|
+
* toggle() {
|
|
47
|
+
* this._barRef.setValue(new Bar());
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* doSomething() {
|
|
51
|
+
* this._barRef.value.xxx();
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
*/
|
|
55
|
+
export class MutableDisposable<T extends IDisposable> implements IDisposable {
|
|
56
|
+
private _value?: T;
|
|
57
|
+
private _isDisposed = false;
|
|
58
|
+
|
|
59
|
+
constructor(value?: T) {
|
|
60
|
+
TRACK_DISPOSABLE(this);
|
|
61
|
+
this.value = value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get value(): T | undefined {
|
|
65
|
+
return this._isDisposed ? undefined : this._value;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
set value(value: T | undefined) {
|
|
69
|
+
if (this._isDisposed || value === this._value) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this._value?.dispose();
|
|
74
|
+
if (value) {
|
|
75
|
+
SET_PARENT_OF_DISPOSABLE(value, this);
|
|
76
|
+
}
|
|
77
|
+
this._value = value;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
clear(): void {
|
|
81
|
+
this.value = undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
dispose(): void {
|
|
85
|
+
this._isDisposed = true;
|
|
86
|
+
MARK_AS_DISPOSED(this);
|
|
87
|
+
this._value?.dispose();
|
|
88
|
+
this._value = undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
release(): T | undefined {
|
|
92
|
+
const oldValue = this._value;
|
|
93
|
+
this._value = undefined;
|
|
94
|
+
if (oldValue) {
|
|
95
|
+
SET_PARENT_OF_DISPOSABLE(oldValue, null);
|
|
96
|
+
}
|
|
97
|
+
return oldValue;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 容器类
|
|
103
|
+
* 通过该容器进行dispose试,可以保证内部的IDisposable一会进行一次dispose
|
|
104
|
+
* 本质是一种防御性质的处理,如果需要使用时,最好有明确的理由
|
|
105
|
+
*/
|
|
106
|
+
export class SafeDisposable<T extends IDisposable> implements IDisposable {
|
|
107
|
+
private _value?: T;
|
|
108
|
+
|
|
109
|
+
constructor(value: T) {
|
|
110
|
+
this._value = value;
|
|
111
|
+
TRACK_DISPOSABLE(this);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get value(): T | undefined {
|
|
115
|
+
return this._value;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
isEmpty() {
|
|
119
|
+
return this._value === undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
dispose() {
|
|
123
|
+
if (!this._value) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this._value.dispose();
|
|
127
|
+
this._value = undefined;
|
|
128
|
+
MARK_AS_DISPOSED(this);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 容器类
|
|
134
|
+
* 引用计数容器,当引用为0时自动执行dispose
|
|
135
|
+
* 注意:初始计数为1,默认构造的地方自动获得引用,如果在栈上构造,记得最后调用release
|
|
136
|
+
*
|
|
137
|
+
* 使用实例:
|
|
138
|
+
* class Foo {
|
|
139
|
+
* private _bar: RefCountedDisposable = new RefCountedDisposable(new Bar());
|
|
140
|
+
*
|
|
141
|
+
* getBar() {
|
|
142
|
+
* this._bar.acquire();
|
|
143
|
+
* return this._bar;
|
|
144
|
+
* }
|
|
145
|
+
* }
|
|
146
|
+
*
|
|
147
|
+
* // 如果在栈上构造
|
|
148
|
+
* const bar = new RefCountedDisposable(new Bar());
|
|
149
|
+
* makeFoo(bar);
|
|
150
|
+
* makeFoo(bar);
|
|
151
|
+
* bar.release();
|
|
152
|
+
*/
|
|
153
|
+
export class RefCountedDisposable<T extends IDisposable> implements IDisposable {
|
|
154
|
+
private _counter: number = 1;
|
|
155
|
+
private _value?: T;
|
|
156
|
+
|
|
157
|
+
constructor(value: T) {
|
|
158
|
+
this._value = value;
|
|
159
|
+
TRACK_DISPOSABLE(this);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
get value(): T | undefined {
|
|
163
|
+
return this._value;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
acquire() {
|
|
167
|
+
if (!this._value) {
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
this._counter++;
|
|
171
|
+
return this;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
release() {
|
|
175
|
+
if (--this._counter === 0) {
|
|
176
|
+
this._value!.dispose();
|
|
177
|
+
this._value = undefined;
|
|
178
|
+
MARK_AS_DISPOSED(this);
|
|
179
|
+
}
|
|
180
|
+
return this;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
dispose() {
|
|
184
|
+
this.release();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* 容器类,表示了一个T生命周期的转移
|
|
190
|
+
*
|
|
191
|
+
* 由于js引用传递的特性,正常情况下,我们默认为传递过来的对象不具备dispose权利
|
|
192
|
+
* class Foo extends Disposable {
|
|
193
|
+
* private readonly _bar = new Bar();
|
|
194
|
+
*
|
|
195
|
+
* constructor(
|
|
196
|
+
* thirdparty: Thirdparty,
|
|
197
|
+
* ) {
|
|
198
|
+
* this._register(this._bar); // class内部构造的,具备dispose权利
|
|
199
|
+
* this._register(thirdparty); // ❌,很少会直接这么写,除非能很确定存在生命周期转移
|
|
200
|
+
* }
|
|
201
|
+
*
|
|
202
|
+
* constructor(
|
|
203
|
+
* thirdparty: TransferDisposable<Thirdparty>, // ✅,明确表示了我依赖了Thirdparty,但是该对象生命周期要归我所有
|
|
204
|
+
* ) {
|
|
205
|
+
* this._register(this._bar);
|
|
206
|
+
* this._register(thirdparty.release()); // ✅,可以直接register
|
|
207
|
+
* }
|
|
208
|
+
* }
|
|
209
|
+
*
|
|
210
|
+
* 注意:
|
|
211
|
+
* 不同于C++中的unique_ptr,该class只作用于转移场景。
|
|
212
|
+
* 所以class理论上只在栈上出现,不应该在堆上存在。
|
|
213
|
+
* 如果出现了需要在堆上存储的场景,可以联系架构侧
|
|
214
|
+
*/
|
|
215
|
+
export class TransferDisposable<T extends IDisposable> extends Disposable {
|
|
216
|
+
private _val?: T;
|
|
217
|
+
|
|
218
|
+
constructor(val: T) {
|
|
219
|
+
super();
|
|
220
|
+
|
|
221
|
+
this._val = val;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
release() {
|
|
225
|
+
// 只能release一次
|
|
226
|
+
lvAssertNotNil(this._val);
|
|
227
|
+
const v = this._val;
|
|
228
|
+
this._val = undefined;
|
|
229
|
+
return v;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
dispose(): void {
|
|
233
|
+
// 虽然它有dispose,但是不应该被执行,应该直接被gc才对
|
|
234
|
+
Logger.warn(new Error('TransferDisposable call dispose.'));
|
|
235
|
+
this._val?.dispose();
|
|
236
|
+
super.dispose();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { makeSafeDisposable } from './disposable-utils';
|
|
2
|
+
|
|
3
|
+
describe('dispose store', () => {
|
|
4
|
+
it('tracker success', () => {
|
|
5
|
+
const mock = vi.fn();
|
|
6
|
+
const safeDisposable = makeSafeDisposable(mock);
|
|
7
|
+
// 正常dispose
|
|
8
|
+
safeDisposable.dispose();
|
|
9
|
+
expect(mock).toHaveBeenCalled();
|
|
10
|
+
|
|
11
|
+
// 只会真正dispose一次
|
|
12
|
+
safeDisposable.dispose();
|
|
13
|
+
expect(mock).toHaveBeenCalledTimes(1);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SafeDisposable, TransferDisposable } from './disposable-t';
|
|
2
|
+
import { EmptyDispose, type IDisposable } from './dispose-base';
|
|
3
|
+
import { MARK_AS_LEAKED } from './tracker';
|
|
4
|
+
|
|
5
|
+
export function makeSafeDisposable(fn: (...args: any) => any) {
|
|
6
|
+
const disposable = new SafeDisposable({
|
|
7
|
+
dispose: fn,
|
|
8
|
+
});
|
|
9
|
+
return disposable;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function makeEmptyDisposable() {
|
|
13
|
+
return EmptyDispose;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 忽略dispose
|
|
17
|
+
export function ignoreDispose(x: IDisposable) {
|
|
18
|
+
MARK_AS_LEAKED(x);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 判断一个thing是否是disposable
|
|
22
|
+
export function isDisposable<E = any>(thing: E): thing is E & IDisposable {
|
|
23
|
+
return typeof (thing as IDisposable).dispose === 'function' && (thing as IDisposable).dispose.length === 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function makeTransferDisposable<T extends IDisposable>(val: T) {
|
|
27
|
+
return new TransferDisposable(val);
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// dispose核心接口
|
|
2
|
+
export type { IDisposable } from './dispose-base';
|
|
3
|
+
|
|
4
|
+
// 记录持有关系的核心数据结构
|
|
5
|
+
export { DisposableStore } from './disposable-store';
|
|
6
|
+
|
|
7
|
+
// dispose常用类型
|
|
8
|
+
// 可以作为IDisposable的基类,自带disposableStore
|
|
9
|
+
export { Disposable } from './disposable-t';
|
|
10
|
+
|
|
11
|
+
// 容器类,允许替换内部的IDisposable,每次替换时,旧value自动dispose
|
|
12
|
+
export { MutableDisposable } from './disposable-t';
|
|
13
|
+
|
|
14
|
+
// 容器类,内部IDisposable对象最多只执行一次dispose
|
|
15
|
+
export { SafeDisposable } from './disposable-t';
|
|
16
|
+
export { makeSafeDisposable } from './disposable-utils';
|
|
17
|
+
|
|
18
|
+
// 容器类,表示一个IDisposable的转移
|
|
19
|
+
export { TransferDisposable } from './disposable-t';
|
|
20
|
+
export { makeTransferDisposable } from './disposable-utils';
|
|
21
|
+
|
|
22
|
+
// 辅助常量,空的IDisposable对象
|
|
23
|
+
export { EmptyDispose } from './dispose-base';
|
|
24
|
+
|
|
25
|
+
// 辅助函数,判断是否是disposable对象
|
|
26
|
+
export { isDisposable } from './disposable-utils';
|
|
27
|
+
|
|
28
|
+
// 辅助函数,定时器disposable化
|
|
29
|
+
export { setDisposableTimeout } from './timer';
|
|
30
|
+
export { setDisposableInterval } from './timer';
|
|
31
|
+
|
|
32
|
+
// 开发阶段辅助函数,忽略disposable泄漏检测
|
|
33
|
+
export { ignoreDispose } from './disposable-utils';
|
|
34
|
+
export { enableTrack, disableTrack, SET_PARENT_OF_DISPOSABLE } from './tracker';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Disposable } from './disposable-t';
|
|
2
|
+
import { makeSafeDisposable } from './disposable-utils';
|
|
3
|
+
import { disposeWithLog } from './logger';
|
|
4
|
+
import type { IDisposableLogger } from './logger';
|
|
5
|
+
|
|
6
|
+
class Bar extends Disposable {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
10
|
+
this._register(makeSafeDisposable(() => {}));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class Foo extends Disposable {
|
|
15
|
+
constructor(mockFunc: () => void) {
|
|
16
|
+
super();
|
|
17
|
+
this._register(new Bar());
|
|
18
|
+
this._register(makeSafeDisposable(mockFunc));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('dispose store', () => {
|
|
23
|
+
it('log success', () => {
|
|
24
|
+
/* eslint-disable no-console */
|
|
25
|
+
console.log = vi.fn();
|
|
26
|
+
const mockDispose = vi.fn();
|
|
27
|
+
const foo1 = new Foo(mockDispose);
|
|
28
|
+
// 默认log
|
|
29
|
+
disposeWithLog(foo1);
|
|
30
|
+
/* eslint-disable no-console */
|
|
31
|
+
expect(console.log).toHaveBeenCalledTimes(1);
|
|
32
|
+
/* eslint-disable no-console */
|
|
33
|
+
expect(console.log).toHaveBeenLastCalledWith([
|
|
34
|
+
['Foo', 'DisposableStore'],
|
|
35
|
+
['DisposableStore', 'Bar'],
|
|
36
|
+
['DisposableStore', 'SafeDisposable'],
|
|
37
|
+
['Bar', 'DisposableStore'],
|
|
38
|
+
['DisposableStore', 'SafeDisposable'],
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
// 自定义log
|
|
42
|
+
const foo2 = new Foo(mockDispose);
|
|
43
|
+
const branchMock = vi.fn();
|
|
44
|
+
const endMock = vi.fn();
|
|
45
|
+
disposeWithLog(
|
|
46
|
+
foo2,
|
|
47
|
+
new (class implements IDisposableLogger {
|
|
48
|
+
branch(from: string, to: string) {
|
|
49
|
+
branchMock(from, to);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
end() {
|
|
53
|
+
endMock();
|
|
54
|
+
}
|
|
55
|
+
})(),
|
|
56
|
+
);
|
|
57
|
+
expect(branchMock).toHaveBeenCalledTimes(5);
|
|
58
|
+
expect(branchMock).toHaveBeenNthCalledWith(1, 'Foo', 'DisposableStore');
|
|
59
|
+
expect(branchMock).toHaveBeenNthCalledWith(2, 'DisposableStore', 'Bar');
|
|
60
|
+
expect(branchMock).toHaveBeenNthCalledWith(3, 'DisposableStore', 'SafeDisposable');
|
|
61
|
+
expect(branchMock).toHaveBeenNthCalledWith(4, 'Bar', 'DisposableStore');
|
|
62
|
+
expect(branchMock).toHaveBeenNthCalledWith(5, 'DisposableStore', 'SafeDisposable');
|
|
63
|
+
expect(endMock).toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Logger } from '@/_internal/logger';
|
|
2
|
+
import type { IDisposable } from './dispose-base';
|
|
3
|
+
|
|
4
|
+
let disposableLogger: IDisposableLogger | null = null;
|
|
5
|
+
|
|
6
|
+
export interface IDisposableLogger {
|
|
7
|
+
branch: (from: string, to: string) => void;
|
|
8
|
+
end: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function setDisposableLogger(logger: IDisposableLogger | null): void {
|
|
12
|
+
disposableLogger = logger;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function makeDefaultLogger() {
|
|
16
|
+
return new (class implements IDisposableLogger {
|
|
17
|
+
private readonly _dep: [string, string][] = [];
|
|
18
|
+
|
|
19
|
+
branch(from: string, to: string): void {
|
|
20
|
+
this._dep.push([from, to]);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
end(): void {
|
|
24
|
+
Logger.log(this._dep);
|
|
25
|
+
}
|
|
26
|
+
})();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 辅助能力 dispose触发时记录
|
|
30
|
+
export function BRANCH_DISPOSE(from: string, to: string) {
|
|
31
|
+
disposableLogger?.branch(from, to);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function disposeWithLog<T extends IDisposable>(x: T, logger: IDisposableLogger = makeDefaultLogger()) {
|
|
35
|
+
setDisposableLogger(logger);
|
|
36
|
+
x.dispose();
|
|
37
|
+
logger.end();
|
|
38
|
+
setDisposableLogger(null);
|
|
39
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { setDisposableTimeout, setDisposableInterval } from './timer';
|
|
2
|
+
|
|
3
|
+
describe('Timeout', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.useFakeTimers();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('setDisposableTimeout', () => {
|
|
9
|
+
let a = 0;
|
|
10
|
+
const disposable = setDisposableTimeout(() => {
|
|
11
|
+
a++;
|
|
12
|
+
}, 10);
|
|
13
|
+
vi.advanceTimersByTime(6);
|
|
14
|
+
disposable.dispose();
|
|
15
|
+
vi.advanceTimersByTime(10);
|
|
16
|
+
expect(a).toBe(0);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('setDisposableInterval', () => {
|
|
20
|
+
let a = 0;
|
|
21
|
+
const disposable = setDisposableInterval(() => {
|
|
22
|
+
a++;
|
|
23
|
+
}, 20);
|
|
24
|
+
vi.advanceTimersByTime(25);
|
|
25
|
+
expect(a).toBe(1);
|
|
26
|
+
disposable.dispose();
|
|
27
|
+
vi.advanceTimersByTime(25);
|
|
28
|
+
expect(a).toBe(1);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IDisposable } from './dispose-base';
|
|
2
|
+
import { makeSafeDisposable } from './disposable-utils';
|
|
3
|
+
|
|
4
|
+
export function setDisposableTimeout(fn: (...args: any[]) => void, timeout: number): IDisposable {
|
|
5
|
+
const handle = setTimeout(() => {
|
|
6
|
+
fn();
|
|
7
|
+
}, timeout);
|
|
8
|
+
return makeSafeDisposable(() => clearTimeout(handle));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function setDisposableInterval(fn: (...args: any[]) => void, timeout: number): IDisposable {
|
|
12
|
+
const handle = setInterval(() => {
|
|
13
|
+
fn();
|
|
14
|
+
}, timeout);
|
|
15
|
+
return makeSafeDisposable(() => clearInterval(handle));
|
|
16
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Disposable } from './disposable-t';
|
|
2
|
+
import { makeSafeDisposable } from './disposable-utils';
|
|
3
|
+
import { disableTrack, enableTrack } from './tracker';
|
|
4
|
+
import type { IDisposableTracker } from './tracker';
|
|
5
|
+
import type { IDisposable } from './dispose-base';
|
|
6
|
+
|
|
7
|
+
vi.useFakeTimers();
|
|
8
|
+
vi.spyOn(global, 'setTimeout');
|
|
9
|
+
|
|
10
|
+
class Bar extends Disposable {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
14
|
+
this._register(makeSafeDisposable(() => {}));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class Foo extends Disposable {
|
|
19
|
+
constructor(mockFunc: () => void) {
|
|
20
|
+
super();
|
|
21
|
+
this._register(new Bar());
|
|
22
|
+
this._register(makeSafeDisposable(mockFunc));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('dispose store', () => {
|
|
27
|
+
it('tracker success', () => {
|
|
28
|
+
let count = 0;
|
|
29
|
+
enableTrack(
|
|
30
|
+
new (class implements IDisposableTracker {
|
|
31
|
+
trackDisposable(x: IDisposable): void {
|
|
32
|
+
count++;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setParent(child: IDisposable, parent: IDisposable | null): void {
|
|
36
|
+
count--;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
markAsDisposed(disposable: IDisposable): void {
|
|
40
|
+
count--;
|
|
41
|
+
}
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
43
|
+
markAsLeaked(disposable: IDisposable): void {}
|
|
44
|
+
})(),
|
|
45
|
+
);
|
|
46
|
+
new Foo(vi.fn());
|
|
47
|
+
// 只剩下根节点
|
|
48
|
+
expect(count).toBe(1);
|
|
49
|
+
disableTrack();
|
|
50
|
+
});
|
|
51
|
+
});
|