@lukekaalim/act-recon 2.0.0 → 3.0.0-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @lukekaalim/act-recon
2
2
 
3
+ ## 3.0.0-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - fdf1557: Fixed issue with multiple changes (where changes after first were children of first) being ignored due to "MustVisit" being misinput each time
8
+
9
+ ## 3.0.0-alpha.0
10
+
11
+ ### Major Changes
12
+
13
+ - b3f6c49: Added debug capabilities and protocol
14
+
3
15
  ## 2.0.0
4
16
 
5
17
  ### Major Changes
package/event.ts CHANGED
@@ -1,34 +1,30 @@
1
1
  export type Subscription = { cancel: () => void };
2
2
  export type EventHandler<T> = (event: T) => unknown;
3
- export type EventMap = Record<string, unknown>;
4
3
 
5
- export type EventEmitter<T extends EventMap> = {
6
- on<K extends keyof T>(type: K, handler: EventHandler<T[K]>): Subscription,
7
- call<K extends keyof T>(type: K, event: T[K]): void;
8
- }
4
+ export type EventEmitter<T> = {
5
+ subscribe(handler: EventHandler<T>): Subscription,
6
+ emit(event: T): void;
7
+ };
9
8
 
10
- export const createEventEmitter = <T extends EventMap>(): EventEmitter<T> => {
11
- type AnyEvent = T[keyof T];
12
- type AnyHandler = EventHandler<AnyEvent>
13
- const handlers = new Map<keyof T, Set<AnyHandler>>();
9
+ export const createEventEmitter = <T>(): EventEmitter<T> => {
10
+ const handlers = new Map<number, EventHandler<T>>();
11
+ let counter = 0;
14
12
 
15
13
  return {
16
- on(type, handler) {
17
- const set = handlers.get(type) || new Set<AnyHandler>();
18
- handlers.set(type, set);
19
- set.add(handler as AnyHandler);
14
+ subscribe(handler) {
15
+ const id = counter++;
16
+ handlers.set(id, handler);
20
17
  return {
21
18
  cancel() {
22
- set.delete(handler as AnyHandler);
19
+ handlers.delete(id);
23
20
  },
24
21
  }
25
22
  },
26
- call(type, event) {
27
- const set = handlers.get(type);
28
- if (!set)
29
- return;
30
- for (const handler of set)
31
- handler(event);
23
+ emit(event) {
24
+ for (const handler of handlers.values())
25
+ try {
26
+ handler(event);
27
+ } finally {}
32
28
  },
33
29
  }
34
30
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lukekaalim/act-recon",
3
3
  "type": "module",
4
- "version": "2.0.0",
4
+ "version": "3.0.0-alpha.1",
5
5
  "main": "mod.ts",
6
6
  "dependencies": {
7
7
  "@lukekaalim/act": "^3.2.0"
package/reconciler.ts CHANGED
@@ -13,7 +13,7 @@ export type Reconciler = {
13
13
  state: ReconcilerState,
14
14
  tree: CommitTree,
15
15
  elements: ElementService,
16
- on: EventEmitter<ReconcilerEvents>["on"],
16
+ subscribe: EventEmitter<ReconcilerEvent>["subscribe"],
17
17
  }
18
18
 
19
19
  export type ReconcilerState = {
@@ -25,14 +25,15 @@ export type ReconcilerState = {
25
25
  pendingTargets: Map<CommitID, CommitRef>,
26
26
  }
27
27
 
28
- export type ReconcilerEvents = {
29
- 'on-thread-start': WorkThread,
30
- 'on-thread-update': WorkThread,
31
- 'on-thread-complete': WorkThread,
32
- }
28
+ export type ReconcilerEvent =
29
+ | { type: 'thread:start', thread: WorkThread }
30
+ | { type: 'thread:update', thread: WorkThread }
31
+ | { type: 'thread:complete', thread: WorkThread }
32
+ | { type: 'thread:new-target', thread: WorkThread }
33
+ | { type: 'thread:new-root', thread: WorkThread }
33
34
 
34
35
  export const createReconciler = (scheduler: Scheduler): Reconciler => {
35
- const events = createEventEmitter<ReconcilerEvents>();
36
+ const events = createEventEmitter<ReconcilerEvent>();
36
37
  const state: ReconcilerState = {
37
38
  thread: null,
38
39
  work: null,
@@ -59,7 +60,7 @@ export const createReconciler = (scheduler: Scheduler): Reconciler => {
59
60
  render(target);
60
61
 
61
62
  WorkThread.apply(completedThread, tree);
62
- events.call('on-thread-complete', completedThread);
63
+ events.emit({ type: 'thread:complete', thread: completedThread });
63
64
 
64
65
  // Run side effects
65
66
  for (const effect of completedThread.pendingEffects) {
@@ -75,7 +76,7 @@ export const createReconciler = (scheduler: Scheduler): Reconciler => {
75
76
  const start = () => {
76
77
  if (!state.thread) {
77
78
  state.thread = WorkThread.new();
78
- events.call('on-thread-start', state.thread);
79
+ events.emit({ type: 'thread:start', thread: state.thread });
79
80
  }
80
81
  if (!state.work) {
81
82
  state.work = scheduler.requestWork(work);
@@ -92,13 +93,13 @@ export const createReconciler = (scheduler: Scheduler): Reconciler => {
92
93
  tree.roots.add(ref);
93
94
  WorkThread.queueMount(thread, ref, element);
94
95
  }
95
- events.call('on-thread-update', thread);
96
+ events.emit({ type: 'thread:new-root', thread });
96
97
  };
97
98
  const render = (ref: CommitRef) => {
98
99
  const thread = start();
99
100
 
100
101
  if (WorkThread.queueTarget(thread, ref, tree)) {
101
- events.call('on-thread-update', thread);
102
+ events.emit({ type: 'thread:new-target', thread });
102
103
  } else {
103
104
  state.pendingTargets.set(ref.id, ref);
104
105
  }
@@ -107,5 +108,5 @@ export const createReconciler = (scheduler: Scheduler): Reconciler => {
107
108
  const tree = CommitTree.new();
108
109
  const elements = ElementService.create(tree, render);
109
110
 
110
- return { mount, render, state, tree, elements, on: events.on };
111
+ return { mount, render, state, tree, elements, subscribe: events.subscribe };
111
112
  }
package/thread.ts CHANGED
@@ -185,8 +185,9 @@ const queueWorkThreadTarget = (thread: WorkThread, ref: CommitRef, tree: CommitT
185
185
  // lead to this commit. If so, make sure ancestor commit
186
186
  // is on the MustVisit so they should make their way down
187
187
  // eventually
188
- for (const id of [...ref.path].reverse().slice(1)) {
189
- thread.mustVisit.set(ref.id, ref);
188
+ for (let i = ref.path.length - 1; i >= 0; i--) {
189
+ const id = ref.path[i];
190
+ thread.mustVisit.add(id);
190
191
 
191
192
  for (const update of thread.pendingUpdates) {
192
193
  // Found an ancestor pending update - it should
@@ -221,7 +222,7 @@ export type WorkThread = {
221
222
  reasons: WorkReason[],
222
223
 
223
224
  mustRender: Map<CommitID, CommitRef>,
224
- mustVisit: Map<CommitID, CommitRef>,
225
+ mustVisit: Set<CommitID>,
225
226
 
226
227
  pendingUpdates: Update[],
227
228
  pendingEffects: EffectTask[],
@@ -242,7 +243,7 @@ export const cloneWorkThread = (thread: WorkThread): WorkThread => {
242
243
  pendingUpdates: [...thread.pendingUpdates],
243
244
  errorNotifications: new Map(thread.errorNotifications),
244
245
 
245
- mustVisit: new Map(thread.mustVisit),
246
+ mustVisit: new Set(thread.mustVisit),
246
247
  mustRender: new Map(thread.mustRender),
247
248
 
248
249
  visited: new Map(thread.visited),
@@ -259,7 +260,7 @@ export const WorkThread = {
259
260
  pendingUpdates: [],
260
261
  errorNotifications: new Map(),
261
262
 
262
- mustVisit: new Map(),
263
+ mustVisit: new Set(),
263
264
  mustRender: new Map(),
264
265
 
265
266
  visited: new Map(),