rask-ui 0.2.1 → 0.2.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/observation.d.ts +1 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +3 -16
- package/dist/observation.test.js +109 -146
- package/dist/tests/observation.test.js +0 -37
- package/dist/tests/patchChildren.test.js +187 -48
- package/dist/vdom/AbstractVNode.d.ts +21 -2
- package/dist/vdom/AbstractVNode.d.ts.map +1 -1
- package/dist/vdom/AbstractVNode.js +166 -17
- package/dist/vdom/ComponentVNode.d.ts +0 -1
- package/dist/vdom/ComponentVNode.d.ts.map +1 -1
- package/dist/vdom/ComponentVNode.js +26 -18
- package/dist/vdom/ElementVNode.d.ts +0 -1
- package/dist/vdom/ElementVNode.d.ts.map +1 -1
- package/dist/vdom/ElementVNode.js +3 -11
- package/dist/vdom/FragmentVNode.d.ts +0 -1
- package/dist/vdom/FragmentVNode.d.ts.map +1 -1
- package/dist/vdom/FragmentVNode.js +3 -4
- package/dist/vdom/RootVNode.d.ts +5 -2
- package/dist/vdom/RootVNode.d.ts.map +1 -1
- package/dist/vdom/RootVNode.js +17 -5
- package/dist/vdom/TextVNode.d.ts +0 -1
- package/dist/vdom/TextVNode.d.ts.map +1 -1
- package/dist/vdom/TextVNode.js +3 -1
- package/package.json +1 -1
package/dist/observation.d.ts
CHANGED
|
@@ -5,11 +5,10 @@ export declare class Signal {
|
|
|
5
5
|
notify(): void;
|
|
6
6
|
}
|
|
7
7
|
export declare class Observer {
|
|
8
|
-
|
|
8
|
+
isDisposed: boolean;
|
|
9
9
|
private signalDisposers;
|
|
10
10
|
private clearSignals;
|
|
11
11
|
private onNotify;
|
|
12
|
-
private isQueued;
|
|
13
12
|
constructor(onNotify: () => void);
|
|
14
13
|
subscribeSignal(signal: Signal): void;
|
|
15
14
|
observe(): () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,aAEjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,WAAW,CAAyB;IAC5C,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAOxB,MAAM;CAGP;AAED,qBAAa,QAAQ;IACnB,
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,aAEjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,WAAW,CAAyB;IAC5C,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAOxB,MAAM;CAGP;AAED,qBAAa,QAAQ;IACnB,UAAU,UAAS;IACnB,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,QAAQ,CAAa;gBACjB,QAAQ,EAAE,MAAM,IAAI;IAGhC,eAAe,CAAC,MAAM,EAAE,MAAM;IAG9B,OAAO;IAOP,OAAO;CAIR"}
|
package/dist/observation.js
CHANGED
|
@@ -15,28 +15,15 @@ export class Signal {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
export class Observer {
|
|
18
|
-
|
|
18
|
+
isDisposed = false;
|
|
19
19
|
signalDisposers = new Set();
|
|
20
20
|
clearSignals() {
|
|
21
21
|
this.signalDisposers.forEach((dispose) => dispose());
|
|
22
22
|
this.signalDisposers.clear();
|
|
23
23
|
}
|
|
24
24
|
onNotify;
|
|
25
|
-
isQueued = false;
|
|
26
25
|
constructor(onNotify) {
|
|
27
|
-
this.onNotify =
|
|
28
|
-
if (this.isQueued) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
queueMicrotask(() => {
|
|
32
|
-
this.isQueued = false;
|
|
33
|
-
if (this._isDisposed) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
onNotify();
|
|
37
|
-
});
|
|
38
|
-
this.isQueued = true;
|
|
39
|
-
};
|
|
26
|
+
this.onNotify = onNotify;
|
|
40
27
|
}
|
|
41
28
|
subscribeSignal(signal) {
|
|
42
29
|
this.signalDisposers.add(signal.subscribe(this.onNotify));
|
|
@@ -50,6 +37,6 @@ export class Observer {
|
|
|
50
37
|
}
|
|
51
38
|
dispose() {
|
|
52
39
|
this.clearSignals();
|
|
53
|
-
this.
|
|
40
|
+
this.isDisposed = true;
|
|
54
41
|
}
|
|
55
42
|
}
|
package/dist/observation.test.js
CHANGED
|
@@ -1,150 +1,113 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from
|
|
2
|
-
import { Signal, Observer, getCurrentObserver } from
|
|
3
|
-
describe(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { Signal, Observer, getCurrentObserver } from "./observation";
|
|
3
|
+
describe("Signal", () => {
|
|
4
|
+
it("should allow subscribing to notifications", () => {
|
|
5
|
+
const signal = new Signal();
|
|
6
|
+
const callback = vi.fn();
|
|
7
|
+
signal.subscribe(callback);
|
|
8
|
+
signal.notify();
|
|
9
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
10
|
+
});
|
|
11
|
+
it("should return a disposer function", () => {
|
|
12
|
+
const signal = new Signal();
|
|
13
|
+
const callback = vi.fn();
|
|
14
|
+
const dispose = signal.subscribe(callback);
|
|
15
|
+
dispose();
|
|
16
|
+
signal.notify();
|
|
17
|
+
expect(callback).not.toHaveBeenCalled();
|
|
18
|
+
});
|
|
19
|
+
it("should handle multiple subscribers", () => {
|
|
20
|
+
const signal = new Signal();
|
|
21
|
+
const callback1 = vi.fn();
|
|
22
|
+
const callback2 = vi.fn();
|
|
23
|
+
signal.subscribe(callback1);
|
|
24
|
+
signal.subscribe(callback2);
|
|
25
|
+
signal.notify();
|
|
26
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
27
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
28
|
+
});
|
|
29
|
+
it("should allow unsubscribing individual callbacks", () => {
|
|
30
|
+
const signal = new Signal();
|
|
31
|
+
const callback1 = vi.fn();
|
|
32
|
+
const callback2 = vi.fn();
|
|
33
|
+
const dispose1 = signal.subscribe(callback1);
|
|
34
|
+
signal.subscribe(callback2);
|
|
35
|
+
dispose1();
|
|
36
|
+
signal.notify();
|
|
37
|
+
expect(callback1).not.toHaveBeenCalled();
|
|
38
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
39
|
+
});
|
|
40
40
|
});
|
|
41
|
-
describe(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// Should not be called synchronously
|
|
56
|
-
expect(callCount).toBe(0);
|
|
57
|
-
// Wait for microtask
|
|
58
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
59
|
-
// Should be called only once due to queuing
|
|
60
|
-
expect(callCount).toBe(1);
|
|
61
|
-
});
|
|
62
|
-
it('should track signals during observation', () => {
|
|
63
|
-
const callback = vi.fn();
|
|
64
|
-
const observer = new Observer(callback);
|
|
65
|
-
const signal = new Signal();
|
|
66
|
-
const dispose = observer.observe();
|
|
67
|
-
observer.subscribeSignal(signal);
|
|
68
|
-
dispose();
|
|
69
|
-
signal.notify();
|
|
70
|
-
return new Promise((resolve) => {
|
|
71
|
-
queueMicrotask(() => {
|
|
72
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
73
|
-
resolve(undefined);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
it('should clear signals when observing again', async () => {
|
|
78
|
-
let callCount = 0;
|
|
79
|
-
const observer = new Observer(() => {
|
|
80
|
-
callCount++;
|
|
81
|
-
});
|
|
82
|
-
const signal1 = new Signal();
|
|
83
|
-
const signal2 = new Signal();
|
|
84
|
-
// First observation
|
|
85
|
-
let dispose = observer.observe();
|
|
86
|
-
observer.subscribeSignal(signal1);
|
|
87
|
-
dispose();
|
|
88
|
-
// Second observation - should clear previous signals
|
|
89
|
-
dispose = observer.observe();
|
|
90
|
-
observer.subscribeSignal(signal2);
|
|
91
|
-
dispose();
|
|
92
|
-
// Notify first signal - should not trigger observer
|
|
93
|
-
signal1.notify();
|
|
94
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
95
|
-
expect(callCount).toBe(0);
|
|
96
|
-
// Notify second signal - should trigger observer
|
|
97
|
-
signal2.notify();
|
|
98
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
99
|
-
expect(callCount).toBe(1);
|
|
100
|
-
});
|
|
101
|
-
it('should dispose of all signal subscriptions', async () => {
|
|
102
|
-
const callback = vi.fn();
|
|
103
|
-
const observer = new Observer(callback);
|
|
104
|
-
const signal = new Signal();
|
|
105
|
-
const dispose = observer.observe();
|
|
106
|
-
observer.subscribeSignal(signal);
|
|
107
|
-
dispose();
|
|
108
|
-
observer.dispose();
|
|
109
|
-
signal.notify();
|
|
110
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
111
|
-
expect(callback).not.toHaveBeenCalled();
|
|
112
|
-
});
|
|
113
|
-
it('should set current observer during observation', () => {
|
|
114
|
-
const observer = new Observer(() => { });
|
|
115
|
-
expect(getCurrentObserver()).toBeUndefined();
|
|
116
|
-
const dispose = observer.observe();
|
|
117
|
-
expect(getCurrentObserver()).toBe(observer);
|
|
118
|
-
dispose();
|
|
119
|
-
expect(getCurrentObserver()).toBeUndefined();
|
|
120
|
-
});
|
|
121
|
-
it('should handle nested observations with stack', () => {
|
|
122
|
-
const observer1 = new Observer(() => { });
|
|
123
|
-
const observer2 = new Observer(() => { });
|
|
124
|
-
const dispose1 = observer1.observe();
|
|
125
|
-
expect(getCurrentObserver()).toBe(observer1);
|
|
126
|
-
const dispose2 = observer2.observe();
|
|
127
|
-
expect(getCurrentObserver()).toBe(observer2);
|
|
128
|
-
dispose2();
|
|
129
|
-
expect(getCurrentObserver()).toBe(observer1);
|
|
130
|
-
dispose1();
|
|
131
|
-
expect(getCurrentObserver()).toBeUndefined();
|
|
41
|
+
describe("Observer", () => {
|
|
42
|
+
it("should track signals during observation", () => {
|
|
43
|
+
const callback = vi.fn();
|
|
44
|
+
const observer = new Observer(callback);
|
|
45
|
+
const signal = new Signal();
|
|
46
|
+
const dispose = observer.observe();
|
|
47
|
+
observer.subscribeSignal(signal);
|
|
48
|
+
dispose();
|
|
49
|
+
signal.notify();
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
queueMicrotask(() => {
|
|
52
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
53
|
+
resolve(undefined);
|
|
54
|
+
});
|
|
132
55
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const signal = new Signal();
|
|
139
|
-
const dispose = observer.observe();
|
|
140
|
-
observer.subscribeSignal(signal);
|
|
141
|
-
dispose();
|
|
142
|
-
// Rapid-fire notifications
|
|
143
|
-
for (let i = 0; i < 100; i++) {
|
|
144
|
-
signal.notify();
|
|
145
|
-
}
|
|
146
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
147
|
-
// Should only be called once
|
|
148
|
-
expect(callCount).toBe(1);
|
|
56
|
+
});
|
|
57
|
+
it("should clear signals when observing again", async () => {
|
|
58
|
+
let callCount = 0;
|
|
59
|
+
const observer = new Observer(() => {
|
|
60
|
+
callCount++;
|
|
149
61
|
});
|
|
62
|
+
const signal1 = new Signal();
|
|
63
|
+
const signal2 = new Signal();
|
|
64
|
+
// First observation
|
|
65
|
+
let dispose = observer.observe();
|
|
66
|
+
observer.subscribeSignal(signal1);
|
|
67
|
+
dispose();
|
|
68
|
+
// Second observation - should clear previous signals
|
|
69
|
+
dispose = observer.observe();
|
|
70
|
+
observer.subscribeSignal(signal2);
|
|
71
|
+
dispose();
|
|
72
|
+
// Notify first signal - should not trigger observer
|
|
73
|
+
signal1.notify();
|
|
74
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
75
|
+
expect(callCount).toBe(0);
|
|
76
|
+
// Notify second signal - should trigger observer
|
|
77
|
+
signal2.notify();
|
|
78
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
79
|
+
expect(callCount).toBe(1);
|
|
80
|
+
});
|
|
81
|
+
it("should dispose of all signal subscriptions", async () => {
|
|
82
|
+
const callback = vi.fn();
|
|
83
|
+
const observer = new Observer(callback);
|
|
84
|
+
const signal = new Signal();
|
|
85
|
+
const dispose = observer.observe();
|
|
86
|
+
observer.subscribeSignal(signal);
|
|
87
|
+
dispose();
|
|
88
|
+
observer.dispose();
|
|
89
|
+
signal.notify();
|
|
90
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
91
|
+
expect(callback).not.toHaveBeenCalled();
|
|
92
|
+
});
|
|
93
|
+
it("should set current observer during observation", () => {
|
|
94
|
+
const observer = new Observer(() => {});
|
|
95
|
+
expect(getCurrentObserver()).toBeUndefined();
|
|
96
|
+
const dispose = observer.observe();
|
|
97
|
+
expect(getCurrentObserver()).toBe(observer);
|
|
98
|
+
dispose();
|
|
99
|
+
expect(getCurrentObserver()).toBeUndefined();
|
|
100
|
+
});
|
|
101
|
+
it("should handle nested observations with stack", () => {
|
|
102
|
+
const observer1 = new Observer(() => {});
|
|
103
|
+
const observer2 = new Observer(() => {});
|
|
104
|
+
const dispose1 = observer1.observe();
|
|
105
|
+
expect(getCurrentObserver()).toBe(observer1);
|
|
106
|
+
const dispose2 = observer2.observe();
|
|
107
|
+
expect(getCurrentObserver()).toBe(observer2);
|
|
108
|
+
dispose2();
|
|
109
|
+
expect(getCurrentObserver()).toBe(observer1);
|
|
110
|
+
dispose1();
|
|
111
|
+
expect(getCurrentObserver()).toBeUndefined();
|
|
112
|
+
});
|
|
150
113
|
});
|
|
@@ -39,26 +39,6 @@ describe("Signal", () => {
|
|
|
39
39
|
});
|
|
40
40
|
});
|
|
41
41
|
describe("Observer", () => {
|
|
42
|
-
it("should queue notifications in microtasks", async () => {
|
|
43
|
-
let callCount = 0;
|
|
44
|
-
const observer = new Observer(() => {
|
|
45
|
-
callCount++;
|
|
46
|
-
});
|
|
47
|
-
const signal = new Signal();
|
|
48
|
-
const dispose = observer.observe();
|
|
49
|
-
observer.subscribeSignal(signal);
|
|
50
|
-
dispose();
|
|
51
|
-
// Trigger multiple notifications
|
|
52
|
-
signal.notify();
|
|
53
|
-
signal.notify();
|
|
54
|
-
signal.notify();
|
|
55
|
-
// Should not be called synchronously
|
|
56
|
-
expect(callCount).toBe(0);
|
|
57
|
-
// Wait for microtask
|
|
58
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
59
|
-
// Should be called only once due to queuing
|
|
60
|
-
expect(callCount).toBe(1);
|
|
61
|
-
});
|
|
62
42
|
it("should track signals during observation", () => {
|
|
63
43
|
const callback = vi.fn();
|
|
64
44
|
const observer = new Observer(callback);
|
|
@@ -130,21 +110,4 @@ describe("Observer", () => {
|
|
|
130
110
|
dispose1();
|
|
131
111
|
expect(getCurrentObserver()).toBeUndefined();
|
|
132
112
|
});
|
|
133
|
-
it("should prevent duplicate notifications while queued", async () => {
|
|
134
|
-
let callCount = 0;
|
|
135
|
-
const observer = new Observer(() => {
|
|
136
|
-
callCount++;
|
|
137
|
-
});
|
|
138
|
-
const signal = new Signal();
|
|
139
|
-
const dispose = observer.observe();
|
|
140
|
-
observer.subscribeSignal(signal);
|
|
141
|
-
dispose();
|
|
142
|
-
// Rapid-fire notifications
|
|
143
|
-
for (let i = 0; i < 100; i++) {
|
|
144
|
-
signal.notify();
|
|
145
|
-
}
|
|
146
|
-
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
147
|
-
// Should only be called once
|
|
148
|
-
expect(callCount).toBe(1);
|
|
149
|
-
});
|
|
150
113
|
});
|