@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 +12 -0
- package/element.ts +10 -4
- package/package.json +1 -1
- package/thread.ts +38 -17
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
|
-
|
|
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
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
|
-
*
|
|
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
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* @
|
|
166
|
-
*
|
|
167
|
-
*
|
|
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
|
|
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(
|
|
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(
|
|
179
|
+
if (thread.visited.has(target.id))
|
|
178
180
|
return false;
|
|
179
181
|
|
|
180
|
-
thread.reasons.push({ type: 'target', ref });
|
|
181
|
-
thread.mustRender.set(
|
|
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 (
|
|
189
|
-
|
|
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:
|
|
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
|
|
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
|
|
283
|
+
mustVisit: new Set(),
|
|
263
284
|
mustRender: new Map(),
|
|
264
285
|
|
|
265
286
|
visited: new Map(),
|