@lukekaalim/act-recon 3.0.0-alpha.0 → 3.0.0-alpha.2

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.2
4
+
5
+ ### Patch Changes
6
+
7
+ - c5e8775: Fix context updates not actually being pushed to the MustRender list
8
+
9
+ ## 3.0.0-alpha.1
10
+
11
+ ### Patch Changes
12
+
13
+ - fdf1557: Fixed issue with multiple changes (where changes after first were children of first) being ignored due to "MustVisit" being misinput each time
14
+
3
15
  ## 3.0.0-alpha.0
4
16
 
5
17
  ### Major Changes
package/element.ts CHANGED
@@ -7,6 +7,7 @@ import { loadHooks } from "./hooks";
7
7
  import { ContextState } from "./context";
8
8
  import { ComponentState, EffectID, EffectTask } from "./state";
9
9
  import { CommitTree } from "./tree";
10
+ import { addRenderTargetToThread, WorkThread } from "./thread";
10
11
 
11
12
  /**
12
13
  * When processing an element, it may produce additional
@@ -17,19 +18,17 @@ export type ElementOutput = {
17
18
  child: Node,
18
19
  reject: null | unknown,
19
20
  effects: EffectTask[],
20
- targets: CommitRef[],
21
21
  };
22
22
  export const ElementOutput = {
23
23
  new: (child: Node): ElementOutput => ({
24
24
  child,
25
25
  reject: null,
26
26
  effects: [],
27
- targets: [],
28
27
  })
29
28
  }
30
29
 
31
30
  export type ElementService = {
32
- render(element: Element, ref: CommitRef): ElementOutput,
31
+ render(element: Element, ref: CommitRef, thread: WorkThread): ElementOutput,
33
32
  clear(ref: Commit): ElementOutput,
34
33
 
35
34
  boundary: Map<CommitID, unknown>,
@@ -45,6 +44,7 @@ export const createElementService = (
45
44
  const render = (
46
45
  element: Element,
47
46
  ref: CommitRef,
47
+ thread: WorkThread,
48
48
  ): ElementOutput => {
49
49
  const output = ElementOutput.new(element.children);
50
50
 
@@ -66,7 +66,13 @@ export const createElementService = (
66
66
  }
67
67
  if (state.value !== element.props.value) {
68
68
  state.value = element.props.value;
69
- output.targets.push(...state.consumers.values());
69
+
70
+ for (const [, consumer] of state.consumers) {
71
+ // there should be no way for the children of the
72
+ // provider to already have been renderer,
73
+ // so we don't check the return value.
74
+ addRenderTargetToThread(thread, consumer);
75
+ }
70
76
  }
71
77
  break;
72
78
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lukekaalim/act-recon",
3
3
  "type": "module",
4
- "version": "3.0.0-alpha.0",
4
+ "version": "3.0.0-alpha.2",
5
5
  "main": "mod.ts",
6
6
  "dependencies": {
7
7
  "@lukekaalim/act": "^3.2.0"
package/thread.ts CHANGED
@@ -83,7 +83,7 @@ const updateWorkThread = (thread: WorkThread, update: Update, tree: CommitTree,
83
83
  thread.visited.set(ref.id, ref);
84
84
 
85
85
  if (next) {
86
- const output = element.render(next, ref);
86
+ const output = element.render(next, ref, thread);
87
87
  if (output.reject) {
88
88
  const errorBoundary = WorkThread.findClosestBoundary(thread, tree, ref);
89
89
  if (errorBoundary) {
@@ -158,35 +158,38 @@ const startWorkThreadUpdate = (thread: WorkThread, ref: CommitRef, prev: Commit
158
158
  }
159
159
 
160
160
  /**
161
- * Request that a commit be re-rendered
161
+ * For a running thread, add an additional "target" to render,
162
+ * which forces the thread to VISIT each commit on the path to the target,
163
+ * and to RENDER the target specifically.
162
164
  *
163
- * If returns false, the update cannot be queued in the current
164
- * thread (maybe it already re-rendered?).
165
- * @param thread
166
- * @param ref
167
- * @returns
165
+ * @param thread
166
+ * @param target
167
+ * @returns `true` if the target was added successfully (or was already in the thread),
168
+ * or `false` if it could not be added for some reason, such as:
169
+ * - The thread has already visited the Commit (a thread will never backtrack)
168
170
  */
169
- const queueWorkThreadTarget = (thread: WorkThread, ref: CommitRef, tree: CommitTree): boolean => {
171
+ export const addRenderTargetToThread = (thread: WorkThread, target: CommitRef): boolean => {
170
172
  // If the thread _already_ has this ref as a target,
171
173
  // do nothing
172
- if (thread.mustRender.has(ref.id))
174
+ if (thread.mustRender.has(target.id))
173
175
  return true;
174
176
 
175
177
  // We cant do work on a commit that has
176
178
  // already been visited
177
- if (thread.visited.has(ref.id))
179
+ if (thread.visited.has(target.id))
178
180
  return false;
179
181
 
180
- thread.reasons.push({ type: 'target', ref });
181
- thread.mustRender.set(ref.id, ref);
182
+ thread.reasons.push({ type: 'target', ref: target });
183
+ thread.mustRender.set(target.id, target);
182
184
 
183
185
  // Search through all the parents, looking to see if
184
186
  // there are any pendingUpdates that might
185
187
  // lead to this commit. If so, make sure ancestor commit
186
188
  // is on the MustVisit so they should make their way down
187
189
  // eventually
188
- for (const id of [...ref.path].reverse().slice(1)) {
189
- thread.mustVisit.set(ref.id, ref);
190
+ for (let i = target.path.length - 1; i >= 0; i--) {
191
+ const id = target.path[i];
192
+ thread.mustVisit.add(id);
190
193
 
191
194
  for (const update of thread.pendingUpdates) {
192
195
  // Found an ancestor pending update - it should
@@ -195,6 +198,24 @@ const queueWorkThreadTarget = (thread: WorkThread, ref: CommitRef, tree: CommitT
195
198
  return true;
196
199
  }
197
200
  }
201
+
202
+ return true;
203
+ }
204
+
205
+ /**
206
+ * Request that a commit be re-rendered
207
+ *
208
+ * If returns false, the update cannot be queued in the current
209
+ * thread (maybe it already re-rendered?).
210
+ * @param thread
211
+ * @param ref
212
+ * @returns
213
+ */
214
+ const queueWorkThreadTarget = (thread: WorkThread, ref: CommitRef, tree: CommitTree): boolean => {
215
+ // Try to add to the thread
216
+ if (!addRenderTargetToThread(thread, ref)) {
217
+ return false;
218
+ }
198
219
  // otherwise, start a new update from the root
199
220
  const prev = tree.commits.get(ref.id) as Commit;
200
221
  startWorkThreadUpdate(thread, ref, prev, prev.element);
@@ -221,7 +242,7 @@ export type WorkThread = {
221
242
  reasons: WorkReason[],
222
243
 
223
244
  mustRender: Map<CommitID, CommitRef>,
224
- mustVisit: Map<CommitID, CommitRef>,
245
+ mustVisit: Set<CommitID>,
225
246
 
226
247
  pendingUpdates: Update[],
227
248
  pendingEffects: EffectTask[],
@@ -242,7 +263,7 @@ export const cloneWorkThread = (thread: WorkThread): WorkThread => {
242
263
  pendingUpdates: [...thread.pendingUpdates],
243
264
  errorNotifications: new Map(thread.errorNotifications),
244
265
 
245
- mustVisit: new Map(thread.mustVisit),
266
+ mustVisit: new Set(thread.mustVisit),
246
267
  mustRender: new Map(thread.mustRender),
247
268
 
248
269
  visited: new Map(thread.visited),
@@ -259,7 +280,7 @@ export const WorkThread = {
259
280
  pendingUpdates: [],
260
281
  errorNotifications: new Map(),
261
282
 
262
- mustVisit: new Map(),
283
+ mustVisit: new Set(),
263
284
  mustRender: new Map(),
264
285
 
265
286
  visited: new Map(),