@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,73 @@
|
|
|
1
|
+
import { Vector } from './vector';
|
|
2
|
+
|
|
3
|
+
describe('Vector', () => {
|
|
4
|
+
let vector: Vector;
|
|
5
|
+
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
// 在每个测试用例之前创建一个新的实例
|
|
8
|
+
vector = new Vector(2, 3);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should return the correct x value', () => {
|
|
12
|
+
expect(vector.x).toBe(2);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return the correct y value', () => {
|
|
16
|
+
expect(vector.y).toBe(3);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should rotate the vector correctly', () => {
|
|
20
|
+
vector.rotate(Math.PI / 2);
|
|
21
|
+
expect(vector.pair()).toEqual([-3, 2]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should calculate the dot product correctly', () => {
|
|
25
|
+
const otherVector = new Vector(4, 5);
|
|
26
|
+
const dotProduct = vector.dot(otherVector);
|
|
27
|
+
expect(dotProduct).toBe(23);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should add another vector correctly', () => {
|
|
31
|
+
const otherVector = new Vector(1, 2);
|
|
32
|
+
vector.add(otherVector);
|
|
33
|
+
expect(vector.pair()).toEqual([3, 5]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should subtract another vector correctly', () => {
|
|
37
|
+
const otherVector = new Vector(1, 2);
|
|
38
|
+
vector.subtract(otherVector);
|
|
39
|
+
expect(vector.pair()).toEqual([1, 1]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should multiply with another vector correctly', () => {
|
|
43
|
+
const otherVector = new Vector(2, 3);
|
|
44
|
+
vector.multiply(otherVector);
|
|
45
|
+
expect(vector.pair()).toEqual([4, 9]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should divide by another vector correctly', () => {
|
|
49
|
+
const otherVector = new Vector(2, 3);
|
|
50
|
+
vector.divide(otherVector);
|
|
51
|
+
expect(vector.pair()).toEqual([1, 1]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should multiply by a scalar correctly', () => {
|
|
55
|
+
vector.multiplyScalar(2);
|
|
56
|
+
expect(vector.pair()).toEqual([4, 6]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should divide by a scalar correctly', () => {
|
|
60
|
+
vector.divideScalar(2);
|
|
61
|
+
expect(vector.pair()).toEqual([1, 1.5]);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should normalize the vector correctly', () => {
|
|
65
|
+
vector.normalize();
|
|
66
|
+
expect(vector.pair()).toEqual([0.5547001962252291, 0.8320502943378437]);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should calculate the length correctly', () => {
|
|
70
|
+
const length = vector.length();
|
|
71
|
+
expect(length).toBeCloseTo(3.605551275463989);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export class Vector {
|
|
2
|
+
constructor(
|
|
3
|
+
private _x: number,
|
|
4
|
+
private _y: number,
|
|
5
|
+
) {}
|
|
6
|
+
|
|
7
|
+
get x() {
|
|
8
|
+
return this._x;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get y() {
|
|
12
|
+
return this._y;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 以原点为中心,渲染
|
|
17
|
+
*/
|
|
18
|
+
rotate(angle: number) {
|
|
19
|
+
const c = Math.cos(angle);
|
|
20
|
+
const s = Math.sin(angle);
|
|
21
|
+
|
|
22
|
+
const x = this._x;
|
|
23
|
+
const y = this._y;
|
|
24
|
+
|
|
25
|
+
this._x = x * c - y * s;
|
|
26
|
+
this._y = x * s + y * c;
|
|
27
|
+
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 与另外一个向量的点积
|
|
33
|
+
*/
|
|
34
|
+
dot(v: Vector) {
|
|
35
|
+
return this._x * v._x + this._y * v._y;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 与另外一个向量相乘
|
|
40
|
+
*/
|
|
41
|
+
add(v: Vector) {
|
|
42
|
+
this._x += v._x;
|
|
43
|
+
this._y += v._y;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 与另外一个向量相减
|
|
49
|
+
*/
|
|
50
|
+
subtract(v: Vector) {
|
|
51
|
+
this._x -= v._x;
|
|
52
|
+
this._y -= v._y;
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 与另外一个向量相乘
|
|
58
|
+
*/
|
|
59
|
+
multiply(v: Vector) {
|
|
60
|
+
this._x *= v._x;
|
|
61
|
+
this._y *= v._y;
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 与另外一个向量相除
|
|
67
|
+
*/
|
|
68
|
+
divide(v: Vector) {
|
|
69
|
+
this._x /= v._x;
|
|
70
|
+
this._y /= v._y;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 乘以某个系数
|
|
76
|
+
*/
|
|
77
|
+
multiplyScalar(scalar: number) {
|
|
78
|
+
this._x *= scalar;
|
|
79
|
+
this._y *= scalar;
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 除以某个系数
|
|
85
|
+
*/
|
|
86
|
+
divideScalar(scalar: number) {
|
|
87
|
+
return this.multiplyScalar(1 / scalar);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 归一化
|
|
92
|
+
*/
|
|
93
|
+
normalize() {
|
|
94
|
+
return this.divideScalar(this.length() || 1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 模长
|
|
99
|
+
*/
|
|
100
|
+
length() {
|
|
101
|
+
return Math.sqrt(this._x * this._x + this._y * this._y);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 克隆
|
|
106
|
+
*/
|
|
107
|
+
clone() {
|
|
108
|
+
return new Vector(this._x, this._y);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
pair() {
|
|
112
|
+
return [this._x, this._y];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AxiosRequestConfig,
|
|
3
|
+
AxiosResponse,
|
|
4
|
+
AxiosInstance,
|
|
5
|
+
AxiosError,
|
|
6
|
+
AxiosRequestHeaders,
|
|
7
|
+
AxiosInterceptorOptions,
|
|
8
|
+
} from 'axios';
|
|
9
|
+
|
|
10
|
+
export const HostNameTypeNameSpace = 'custom-host-name-type';
|
|
11
|
+
|
|
12
|
+
export interface FetchOptions {
|
|
13
|
+
url: string;
|
|
14
|
+
params?: Record<string, any>;
|
|
15
|
+
method?: 'GET' | 'POST';
|
|
16
|
+
header?: Record<string, any>;
|
|
17
|
+
data?: Record<string, any>;
|
|
18
|
+
needCommonParams?: boolean;
|
|
19
|
+
needTiming?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 请求配置
|
|
23
|
+
export interface NetworkRequestConfig<D = any> extends AxiosRequestConfig<D> {
|
|
24
|
+
// web扩展,只对web生效
|
|
25
|
+
[HostNameTypeNameSpace]?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface BaseNetworkErrorOptions<T = unknown, D = any> {
|
|
29
|
+
message?: string;
|
|
30
|
+
error?: Error;
|
|
31
|
+
code?: string;
|
|
32
|
+
config?: NetworkMiddleRequestConfig;
|
|
33
|
+
request?: any;
|
|
34
|
+
response?: NetworkResponse<T, D>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface NetworkErrorFromMessageOptions<T = unknown, D = any> extends BaseNetworkErrorOptions<T, D> {
|
|
38
|
+
message: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface NetworkErrorFromErrorOptions<T = unknown, D = any> extends BaseNetworkErrorOptions<T, D> {
|
|
42
|
+
error: Error;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type NetworkErrorOptions<T = unknown, D = any> =
|
|
46
|
+
| NetworkErrorFromMessageOptions<T, D>
|
|
47
|
+
| NetworkErrorFromErrorOptions<T, D>;
|
|
48
|
+
|
|
49
|
+
// 请求结果
|
|
50
|
+
export type NetworkResponse<T = any, D = any> = Omit<AxiosResponse<T, D>, 'config'> & {
|
|
51
|
+
// 覆盖config字段,增加扩展
|
|
52
|
+
// 注意:不是写错,就是NetworkMiddleRequestConfig,并非NetworkRequestConfig
|
|
53
|
+
config: NetworkMiddleRequestConfig<D>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// 请求失败时,reject获取的对象
|
|
57
|
+
export type NetworkError<T = unknown, D = any> = AxiosError<T, D> & {
|
|
58
|
+
// 平替isAxiosError标记,表示内部错误
|
|
59
|
+
isNetworkError: boolean;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// 请求经过中间件时配置
|
|
63
|
+
export interface NetworkMiddleRequestConfig<D = any> extends NetworkRequestConfig<D> {
|
|
64
|
+
headers: AxiosRequestHeaders;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 为了支持中间件req、res类型扩展,单独声明InterceptorManager类型
|
|
68
|
+
export interface InterceptorManager<V> {
|
|
69
|
+
use(
|
|
70
|
+
onFulfilled?: ((value: V) => V | Promise<V>) | null,
|
|
71
|
+
onRejected?: ((error: any) => any) | null,
|
|
72
|
+
options?: AxiosInterceptorOptions,
|
|
73
|
+
): number;
|
|
74
|
+
eject(id: number): void;
|
|
75
|
+
clear(): void;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// axios实例
|
|
79
|
+
export type NetworkClientInstance = Omit<AxiosInstance, 'interceptors'> & {
|
|
80
|
+
// 支持中间件req、res类型扩展,覆盖interceptors
|
|
81
|
+
interceptors: {
|
|
82
|
+
request: InterceptorManager<NetworkMiddleRequestConfig>;
|
|
83
|
+
response: InterceptorManager<NetworkResponse>;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// 重新声明,为了参数覆盖
|
|
87
|
+
request: <T = any, R = NetworkResponse<T>, D = any>(
|
|
88
|
+
configOrUrl: NetworkRequestConfig<D> | string,
|
|
89
|
+
config?: NetworkRequestConfig<D>,
|
|
90
|
+
) => Promise<R>;
|
|
91
|
+
get: <T = any, R = NetworkResponse<T>, D = any>(
|
|
92
|
+
url: string,
|
|
93
|
+
config?: Omit<NetworkRequestConfig<D>, 'url'>,
|
|
94
|
+
) => Promise<R>;
|
|
95
|
+
post: <T = any, R = NetworkResponse<T>, D = any>(
|
|
96
|
+
url: string,
|
|
97
|
+
data?: D,
|
|
98
|
+
config?: Omit<NetworkRequestConfig<D>, 'url'>,
|
|
99
|
+
) => Promise<R>;
|
|
100
|
+
|
|
101
|
+
// 重新声明可直接调用,否则会丢失该能力
|
|
102
|
+
<T = any, R = NetworkResponse<T>, D = any>(config: NetworkRequestConfig<D>): Promise<R>;
|
|
103
|
+
<T = any, R = NetworkResponse<T>, D = any>(url: string, config?: NetworkRequestConfig<D>): Promise<R>;
|
|
104
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import axios, { AxiosError } from 'axios';
|
|
2
|
+
import type { NetworkRequestConfig, NetworkClientInstance } from '.';
|
|
3
|
+
import type { NetworkErrorOptions } from './client.interface';
|
|
4
|
+
|
|
5
|
+
export function createClient(config?: NetworkRequestConfig): NetworkClientInstance {
|
|
6
|
+
return axios.create(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class NetworkError<T = unknown, D = any> extends AxiosError<T, D> {
|
|
10
|
+
constructor(opts: NetworkErrorOptions<T, D>) {
|
|
11
|
+
let message;
|
|
12
|
+
|
|
13
|
+
if (opts.message) {
|
|
14
|
+
message = opts.message;
|
|
15
|
+
} else if (opts.error) {
|
|
16
|
+
message = opts.error.message;
|
|
17
|
+
}
|
|
18
|
+
super(message, opts.code, opts.config, opts.request, opts.response);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get isNetworkError() {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { HostNameTypeNameSpace } from './client.interface';
|
|
2
|
+
export type { NetworkRequestConfig } from './client.interface';
|
|
3
|
+
export type { NetworkResponse } from './client.interface';
|
|
4
|
+
|
|
5
|
+
export type { NetworkMiddleRequestConfig } from './client.interface';
|
|
6
|
+
export type { NetworkError } from './client.interface';
|
|
7
|
+
|
|
8
|
+
export type { NetworkClientInstance } from './client.interface';
|
|
9
|
+
|
|
10
|
+
export { addRetryPlugin } from './plugins/retry';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NetworkClientInstance,
|
|
3
|
+
NetworkError,
|
|
4
|
+
NetworkRequestConfig,
|
|
5
|
+
} from '../client.interface';
|
|
6
|
+
|
|
7
|
+
export const NAME_SPACE = 'network-client-retry-plugin';
|
|
8
|
+
|
|
9
|
+
type RetryConfig = {
|
|
10
|
+
lastRequestTime: number;
|
|
11
|
+
retryCount: number;
|
|
12
|
+
canRetry?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type CustomNetworkConfig = NetworkRequestConfig & {
|
|
16
|
+
[NAME_SPACE]?: RetryConfig;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type RetryOptions = {
|
|
20
|
+
retries?: number; // default retry times
|
|
21
|
+
resetTimeout?: boolean; // if reset timeout between retries, default is true
|
|
22
|
+
isRetry?: (error: NetworkError) => boolean;
|
|
23
|
+
retryDelay?: ((count: number) => number) | number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function getCurrentState(config: CustomNetworkConfig): RetryConfig {
|
|
27
|
+
const currentState = config[NAME_SPACE] || ({
|
|
28
|
+
lastRequestTime: 0,
|
|
29
|
+
retryCount: 0,
|
|
30
|
+
} satisfies RetryConfig);
|
|
31
|
+
return currentState;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function fixConfig(networkClient: NetworkClientInstance, config: any) {
|
|
35
|
+
// @ts-expect-error type error
|
|
36
|
+
if (networkClient.defaults.agent === config.agent) {
|
|
37
|
+
delete config.agent;
|
|
38
|
+
}
|
|
39
|
+
if (networkClient.defaults.httpAgent === config.httpAgent) {
|
|
40
|
+
delete config.httpAgent;
|
|
41
|
+
}
|
|
42
|
+
if (networkClient.defaults.httpsAgent === config.httpsAgent) {
|
|
43
|
+
delete config.httpsAgent;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function addRetryPlugin(
|
|
48
|
+
networkClient: NetworkClientInstance,
|
|
49
|
+
options: RetryOptions = {},
|
|
50
|
+
): NetworkClientInstance {
|
|
51
|
+
networkClient.interceptors.request.use((config) => {
|
|
52
|
+
const state = getCurrentState(config as NetworkRequestConfig);
|
|
53
|
+
state.lastRequestTime = Date.now();
|
|
54
|
+
(config as CustomNetworkConfig)[NAME_SPACE] = state;
|
|
55
|
+
return config;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
networkClient.interceptors.response.use(undefined, (error) => {
|
|
59
|
+
const config = error?.config;
|
|
60
|
+
if (!config) {
|
|
61
|
+
return Promise.reject(error);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const {
|
|
65
|
+
retries = 1,
|
|
66
|
+
isRetry = () => true, // isNetworkOrIdempotentRequestError
|
|
67
|
+
retryDelay = 200,
|
|
68
|
+
resetTimeout = true,
|
|
69
|
+
} = { ...options, ...config?.[NAME_SPACE] };
|
|
70
|
+
|
|
71
|
+
const state = getCurrentState(config);
|
|
72
|
+
|
|
73
|
+
// canRetry & isRetry just need one
|
|
74
|
+
const needRetry = (isRetry(error) || state.canRetry) && state.retryCount < retries;
|
|
75
|
+
if (needRetry) {
|
|
76
|
+
state.retryCount += 1;
|
|
77
|
+
const delay = typeof retryDelay === 'number' ? retryDelay : retryDelay(state.retryCount, error);
|
|
78
|
+
|
|
79
|
+
// Axios fails merging this configuration to the default configuration because it has an issue
|
|
80
|
+
// with circular structures: https://github.com/mzabriskie/axios/issues/370
|
|
81
|
+
fixConfig(networkClient, config);
|
|
82
|
+
|
|
83
|
+
if (!resetTimeout && config.timeout && state.lastRequestTime) {
|
|
84
|
+
const lastRequestDuration = Date.now() - state.lastRequestTime;
|
|
85
|
+
// Minimum 1ms timeout (passing 0 or less to XHR means no timeout)
|
|
86
|
+
config.timeout = Math.max(config.timeout - lastRequestDuration - delay, 1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
config.transformRequest = [(data: any) => data];
|
|
90
|
+
|
|
91
|
+
return new Promise((resolve) => setTimeout(() => resolve(networkClient(config)), delay));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return Promise.reject(error);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return networkClient;
|
|
98
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { deepClone } from './deep-clone';
|
|
2
|
+
|
|
3
|
+
describe('deepClone function', () => {
|
|
4
|
+
test('should return null when given null', () => {
|
|
5
|
+
expect(deepClone(null)).toBeNull();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test('should return undefined when given undefined', () => {
|
|
9
|
+
expect(deepClone(undefined)).toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('should return the same value when given a non-object primitive', () => {
|
|
13
|
+
expect(deepClone(123)).toBe(123);
|
|
14
|
+
expect(deepClone('hello')).toBe('hello');
|
|
15
|
+
expect(deepClone(true)).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('should return a deep clone of the object', () => {
|
|
19
|
+
const obj = {
|
|
20
|
+
name: 'John',
|
|
21
|
+
age: 25,
|
|
22
|
+
hobbies: ['reading', 'coding'],
|
|
23
|
+
address: {
|
|
24
|
+
city: 'New York',
|
|
25
|
+
country: 'USA',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const clonedObj = deepClone(obj);
|
|
29
|
+
|
|
30
|
+
expect(clonedObj).toEqual(obj);
|
|
31
|
+
expect(clonedObj === obj).toBe(false); // check if it's a deep clone
|
|
32
|
+
expect(clonedObj.address === obj.address).toBe(false); // check if nested objects are also deeply cloned
|
|
33
|
+
expect(Array.isArray(clonedObj.hobbies)).toBe(true); // check if arrays are cloned
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('should return the same RegExp object when an instance of a RegExp is passed', () => {
|
|
37
|
+
const regex = /abc/;
|
|
38
|
+
expect(deepClone(regex)).toBe(regex);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function deepClone<T>(obj: T): T {
|
|
2
|
+
if (!obj || typeof obj !== 'object') {
|
|
3
|
+
return obj;
|
|
4
|
+
}
|
|
5
|
+
if (obj instanceof RegExp) {
|
|
6
|
+
return obj;
|
|
7
|
+
}
|
|
8
|
+
const result: any = Array.isArray(obj) ? [] : {};
|
|
9
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
10
|
+
result[key] = value && typeof value === 'object' ? deepClone(value) : value;
|
|
11
|
+
});
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { deepEqual } from './deep-equal';
|
|
2
|
+
|
|
3
|
+
describe('deep-equal', () => {
|
|
4
|
+
it('deep-equal', () => {
|
|
5
|
+
expect(deepEqual(null, null)).toBeTruthy();
|
|
6
|
+
expect(deepEqual(undefined, undefined)).toBeTruthy();
|
|
7
|
+
expect(deepEqual(1234, 1234)).toBeTruthy();
|
|
8
|
+
expect(deepEqual('', '')).toBeTruthy();
|
|
9
|
+
expect(deepEqual('1234', '1234')).toBeTruthy();
|
|
10
|
+
expect(deepEqual([], [])).toBeTruthy();
|
|
11
|
+
expect(
|
|
12
|
+
deepEqual(
|
|
13
|
+
[
|
|
14
|
+
[1, 2, 3],
|
|
15
|
+
[4, 5, 6],
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
[1, 2, 3],
|
|
19
|
+
[4, 5, 6],
|
|
20
|
+
],
|
|
21
|
+
),
|
|
22
|
+
).toBeTruthy();
|
|
23
|
+
expect(deepEqual({}, {})).toBeTruthy();
|
|
24
|
+
expect(deepEqual({ a: 1, b: '123' }, { a: 1, b: '123' })).toBeTruthy();
|
|
25
|
+
expect(deepEqual({ a: { b: 1, c: 2 }, b: 3 }, { a: { b: 1, c: 2 }, b: 3 })).toBeTruthy();
|
|
26
|
+
|
|
27
|
+
expect(deepEqual(null, undefined)).toBeFalsy();
|
|
28
|
+
expect(deepEqual(null, '')).toBeFalsy();
|
|
29
|
+
expect(deepEqual(null, [])).toBeFalsy();
|
|
30
|
+
expect(deepEqual(null, {})).toBeFalsy();
|
|
31
|
+
expect(deepEqual(null, 0)).toBeFalsy();
|
|
32
|
+
expect(deepEqual(undefined, '')).toBeFalsy();
|
|
33
|
+
expect(deepEqual(undefined, [])).toBeFalsy();
|
|
34
|
+
expect(deepEqual(undefined, {})).toBeFalsy();
|
|
35
|
+
expect(deepEqual(undefined, 0)).toBeFalsy();
|
|
36
|
+
expect(deepEqual('', [])).toBeFalsy();
|
|
37
|
+
expect(deepEqual('', {})).toBeFalsy();
|
|
38
|
+
expect(deepEqual('', 0)).toBeFalsy();
|
|
39
|
+
expect(deepEqual([], {})).toBeFalsy();
|
|
40
|
+
expect(deepEqual([], 0)).toBeFalsy();
|
|
41
|
+
expect(deepEqual('1234', 1234)).toBeFalsy();
|
|
42
|
+
expect(
|
|
43
|
+
deepEqual(
|
|
44
|
+
[
|
|
45
|
+
[1, 2, 3],
|
|
46
|
+
[4, 5, 6],
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
[1, 2, 3],
|
|
50
|
+
[4, 5, 6000],
|
|
51
|
+
],
|
|
52
|
+
),
|
|
53
|
+
).toBeFalsy();
|
|
54
|
+
expect(deepEqual({ a: { b: 1, c: 2 }, b: 3 }, { b: 3, a: { b: 9, c: 2 } })).toBeFalsy();
|
|
55
|
+
|
|
56
|
+
// 判断一下循环引用
|
|
57
|
+
const a1: any = {};
|
|
58
|
+
// b1存在循环引用
|
|
59
|
+
const b1 = { a: a1, b: 1 };
|
|
60
|
+
a1.b = b1;
|
|
61
|
+
|
|
62
|
+
// b2没有循环引用
|
|
63
|
+
const b2 = { a: {}, b: 1 };
|
|
64
|
+
expect(deepEqual(b1, b2)).toBeFalsy();
|
|
65
|
+
expect(deepEqual(b2, b1)).toBeFalsy();
|
|
66
|
+
|
|
67
|
+
const a3: any = {};
|
|
68
|
+
const b3 = { a: a3, b: 1 };
|
|
69
|
+
a3.b = b3;
|
|
70
|
+
expect(() => {
|
|
71
|
+
deepEqual(b3, b1);
|
|
72
|
+
}).toThrow();
|
|
73
|
+
expect(() => {
|
|
74
|
+
deepEqual(b1, b3);
|
|
75
|
+
}).toThrow();
|
|
76
|
+
|
|
77
|
+
const a4 = { a: 111 };
|
|
78
|
+
// b4出现key指向同一个地址,但是并没有成为环,不会error
|
|
79
|
+
const b4 = { a: a4, aa: a4 };
|
|
80
|
+
expect(() => {
|
|
81
|
+
deepEqual(b4, { a: { a: 111 }, aa: {} });
|
|
82
|
+
}).not.toThrow();
|
|
83
|
+
expect(deepEqual(b4, { a: { a: 111 }, aa: {} })).toBeFalsy();
|
|
84
|
+
expect(deepEqual(b4, { a: { a: 111 }, aa: { a: 111 } })).toBeTruthy();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { lvAssert } from '../assert';
|
|
2
|
+
|
|
3
|
+
function equalsInternal(lhs: any, rhs: any, seen: Set<any>): boolean {
|
|
4
|
+
if (lhs === rhs) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
if (lhs === null || lhs === undefined || rhs === null || rhs === undefined) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
if (typeof lhs !== typeof rhs) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (typeof lhs !== 'object') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
lvAssert(!seen.has(lhs), 'arguments object has circular.');
|
|
17
|
+
seen.add(lhs);
|
|
18
|
+
if (Array.isArray(lhs) !== Array.isArray(rhs)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (Array.isArray(lhs)) {
|
|
23
|
+
if (lhs.length !== rhs.length) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
for (let i = 0; i < lhs.length; i++) {
|
|
27
|
+
if (!equalsInternal(lhs[i], rhs[i], seen)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
const lhsKeys: string[] = Object.keys(lhs);
|
|
33
|
+
lhsKeys.sort();
|
|
34
|
+
|
|
35
|
+
const rhsKeys: string[] = Object.keys(rhs);
|
|
36
|
+
rhsKeys.sort();
|
|
37
|
+
|
|
38
|
+
if (!equalsInternal(lhsKeys, rhsKeys, seen)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
42
|
+
for (let i = 0; i < lhsKeys.length; i++) {
|
|
43
|
+
if (!equalsInternal(lhs[lhsKeys[i]], rhs[lhsKeys[i]], seen)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
seen.delete(lhs);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 提供对象的深度对比是否相等
|
|
54
|
+
*
|
|
55
|
+
* 目前支持的是js中的基础类型,如果需要支持一些高级类型,请联系基建侧同学。
|
|
56
|
+
* 注意:对象内部出现循环依赖时,会throw error
|
|
57
|
+
*/
|
|
58
|
+
export function deepEqual(lhs: any, rhs: any): boolean {
|
|
59
|
+
return equalsInternal(lhs, rhs, new Set());
|
|
60
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
let _isWindows = false;
|
|
3
|
+
let _isMac = false;
|
|
4
|
+
let _isLinux = false;
|
|
5
|
+
let _isWeb = false;
|
|
6
|
+
let _isIOS = false;
|
|
7
|
+
let _isAndroid = false;
|
|
8
|
+
let _isMobile = false;
|
|
9
|
+
let _isIPad = false;
|
|
10
|
+
let _isFirefox = false;
|
|
11
|
+
let _isChrome = false;
|
|
12
|
+
let _isSafari = false;
|
|
13
|
+
let _userAgent: string | undefined;
|
|
14
|
+
|
|
15
|
+
// Web environment
|
|
16
|
+
if (typeof navigator === 'object') {
|
|
17
|
+
_userAgent = navigator.userAgent;
|
|
18
|
+
_isWindows = _userAgent.indexOf('Windows') >= 0;
|
|
19
|
+
_isIOS =
|
|
20
|
+
(_userAgent.indexOf('Macintosh') >= 0 ||
|
|
21
|
+
_userAgent.indexOf('iPad') >= 0 ||
|
|
22
|
+
_userAgent.indexOf('iPhone') >= 0) &&
|
|
23
|
+
Boolean(navigator.maxTouchPoints) &&
|
|
24
|
+
navigator.maxTouchPoints > 0;
|
|
25
|
+
_isAndroid = _userAgent.indexOf('Android') >= 0;
|
|
26
|
+
_isLinux = _userAgent.indexOf('Linux') >= 0;
|
|
27
|
+
_isMobile = _userAgent.indexOf('Mobi') >= 0;
|
|
28
|
+
_isIPad = _userAgent.indexOf('iPad') >= 0;
|
|
29
|
+
_isMac = !_isMobile && _userAgent.indexOf('Macintosh') >= 0;
|
|
30
|
+
_isFirefox = /firefox/i.test(_userAgent);
|
|
31
|
+
_isChrome = /chrome/i.test(_userAgent);
|
|
32
|
+
_isSafari = /^((?!chrome|android).)*safari/i.test(_userAgent);
|
|
33
|
+
_isWeb = true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const isWindows = _isWindows;
|
|
37
|
+
export const isMac = _isMac;
|
|
38
|
+
export const isLinux = _isLinux;
|
|
39
|
+
export const isWeb = _isWeb;
|
|
40
|
+
export const isIOS = _isIOS;
|
|
41
|
+
export const isAndroid = _isAndroid;
|
|
42
|
+
export const isIPad = _isIPad;
|
|
43
|
+
export const isMobile = _isMobile;
|
|
44
|
+
export const isChrome = _isChrome;
|
|
45
|
+
export const isFirefox = _isFirefox;
|
|
46
|
+
export const isSafari = _isSafari;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 判断是否为 Arc 浏览器
|
|
50
|
+
* arc 浏览器判定方式比较奇特,无法通过 UA 判断
|
|
51
|
+
* https://stackoverflow.com/questions/76123232/can-javascript-detect-the-arc-browser
|
|
52
|
+
*/
|
|
53
|
+
export function isArcBrowser(): boolean {
|
|
54
|
+
return getComputedStyle(document.documentElement).getPropertyValue('--arc-palette-title') ? true : false;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** ace2.0 不再提供这个方法 用于判断是否为浏览器环境*/
|
|
58
|
+
export function isBrowser(): boolean {
|
|
59
|
+
return (
|
|
60
|
+
typeof window !== 'undefined' &&
|
|
61
|
+
typeof window.document !== 'undefined' &&
|
|
62
|
+
typeof window.document.createElement !== 'undefined'
|
|
63
|
+
);
|
|
64
|
+
}
|