kiru 0.47.1 → 0.48.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/dist/appContext.d.ts.map +1 -1
- package/dist/appContext.js +3 -5
- package/dist/appContext.js.map +1 -1
- package/dist/constants.d.ts +4 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -4
- package/dist/constants.js.map +1 -1
- package/dist/customEvents.d.ts +6 -0
- package/dist/customEvents.d.ts.map +1 -0
- package/dist/customEvents.js +12 -0
- package/dist/customEvents.js.map +1 -0
- package/dist/dom.d.ts +3 -1
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +102 -102
- package/dist/dom.js.map +1 -1
- package/dist/globalContext.d.ts +4 -3
- package/dist/globalContext.d.ts.map +1 -1
- package/dist/globalContext.js +0 -2
- package/dist/globalContext.js.map +1 -1
- package/dist/hooks/useAsync.d.ts +2 -13
- package/dist/hooks/useAsync.d.ts.map +1 -1
- package/dist/hooks/useAsync.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/lazy.d.ts +2 -2
- package/dist/lazy.d.ts.map +1 -1
- package/dist/lazy.js.map +1 -1
- package/dist/portal.d.ts +2 -2
- package/dist/portal.d.ts.map +1 -1
- package/dist/profiling.d.ts +2 -2
- package/dist/profiling.d.ts.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +13 -10
- package/dist/reconciler.js.map +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +51 -156
- package/dist/scheduler.js.map +1 -1
- package/dist/swr.d.ts +6 -17
- package/dist/swr.d.ts.map +1 -1
- package/dist/swr.js +26 -18
- package/dist/swr.js.map +1 -1
- package/dist/transition.d.ts +2 -2
- package/dist/transition.d.ts.map +1 -1
- package/dist/types.d.ts +20 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +57 -38
- package/dist/types.dom.d.ts.map +1 -1
- package/dist/types.utils.d.ts +31 -19
- package/dist/types.utils.d.ts.map +1 -1
- package/dist/utils.d.ts +1 -10
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +9 -56
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/appContext.ts +3 -5
- package/src/constants.ts +9 -4
- package/src/customEvents.ts +22 -0
- package/src/dom.ts +124 -113
- package/src/globalContext.ts +4 -6
- package/src/hooks/useAsync.ts +7 -24
- package/src/index.ts +7 -4
- package/src/lazy.ts +6 -2
- package/src/portal.ts +1 -1
- package/src/profiling.ts +1 -1
- package/src/reconciler.ts +13 -16
- package/src/scheduler.ts +69 -158
- package/src/swr.ts +28 -37
- package/src/transition.ts +1 -1
- package/src/types.dom.ts +98 -36
- package/src/types.ts +12 -10
- package/src/types.utils.ts +43 -14
- package/src/utils.ts +7 -74
package/src/scheduler.ts
CHANGED
|
@@ -7,9 +7,18 @@ import {
|
|
|
7
7
|
$CONTEXT_PROVIDER,
|
|
8
8
|
CONSECUTIVE_DIRTY_LIMIT,
|
|
9
9
|
FLAG_DELETION,
|
|
10
|
+
FLAG_DIRTY,
|
|
10
11
|
FLAG_MEMO,
|
|
12
|
+
FLAG_NOOP,
|
|
11
13
|
} from "./constants.js"
|
|
12
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
commitDeletion,
|
|
16
|
+
commitWork,
|
|
17
|
+
createDom,
|
|
18
|
+
hydrateDom,
|
|
19
|
+
onAfterFlushDomChanges,
|
|
20
|
+
onBeforeFlushDomChanges,
|
|
21
|
+
} from "./dom.js"
|
|
13
22
|
import { __DEV__ } from "./env.js"
|
|
14
23
|
import { KiruError } from "./error.js"
|
|
15
24
|
import { hookIndex, node, renderMode } from "./globals.js"
|
|
@@ -17,10 +26,8 @@ import { hydrationStack } from "./hydration.js"
|
|
|
17
26
|
import { assertValidElementProps } from "./props.js"
|
|
18
27
|
import { reconcileChildren } from "./reconciler.js"
|
|
19
28
|
import {
|
|
20
|
-
willMemoBlockUpdate,
|
|
21
29
|
latest,
|
|
22
30
|
traverseApply,
|
|
23
|
-
vNodeContains,
|
|
24
31
|
isExoticType,
|
|
25
32
|
getVNodeAppContext,
|
|
26
33
|
} from "./utils.js"
|
|
@@ -29,9 +36,7 @@ import type { AppContext } from "./appContext"
|
|
|
29
36
|
type VNode = Kiru.VNode
|
|
30
37
|
|
|
31
38
|
let appCtx: AppContext | null
|
|
32
|
-
let nextUnitOfWork: VNode | null = null
|
|
33
39
|
let treesInProgress: VNode[] = []
|
|
34
|
-
let currentTreeIndex = 0
|
|
35
40
|
let isRunningOrQueued = false
|
|
36
41
|
let nextIdleEffects: (() => void)[] = []
|
|
37
42
|
let deletions: VNode[] = []
|
|
@@ -39,7 +44,6 @@ let isImmediateEffectsMode = false
|
|
|
39
44
|
let immediateEffectDirtiedRender = false
|
|
40
45
|
let isRenderDirtied = false
|
|
41
46
|
let consecutiveDirtyCount = 0
|
|
42
|
-
let pendingContextChanges = new Set<ContextProviderNode<any>>()
|
|
43
47
|
let preEffects: Array<Function> = []
|
|
44
48
|
let postEffects: Array<Function> = []
|
|
45
49
|
let animationFrameHandle = -1
|
|
@@ -65,15 +69,21 @@ export function flushSync() {
|
|
|
65
69
|
doWork()
|
|
66
70
|
}
|
|
67
71
|
|
|
72
|
+
export function renderRootSync(rootNode: VNode) {
|
|
73
|
+
rootNode.flags |= FLAG_DIRTY
|
|
74
|
+
treesInProgress.push(rootNode)
|
|
75
|
+
if (!isRunningOrQueued) {
|
|
76
|
+
isRunningOrQueued = true
|
|
77
|
+
doWork()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
68
81
|
/**
|
|
69
82
|
* Queues a node for an update. Has no effect if the node is already deleted or marked for deletion.
|
|
70
83
|
*/
|
|
71
84
|
export function requestUpdate(vNode: VNode): void {
|
|
72
|
-
if (vNode.flags & FLAG_DELETION) return
|
|
73
85
|
if (renderMode.current === "hydrate") {
|
|
74
|
-
return nextIdle(() =>
|
|
75
|
-
vNode.flags & FLAG_DELETION || queueUpdate(vNode)
|
|
76
|
-
})
|
|
86
|
+
return nextIdle(() => queueUpdate(vNode))
|
|
77
87
|
}
|
|
78
88
|
queueUpdate(vNode)
|
|
79
89
|
}
|
|
@@ -106,91 +116,14 @@ function queueUpdate(vNode: VNode) {
|
|
|
106
116
|
return
|
|
107
117
|
}
|
|
108
118
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return
|
|
112
|
-
}
|
|
119
|
+
if (vNode.flags & (FLAG_DIRTY | FLAG_DELETION)) return
|
|
120
|
+
vNode.flags |= FLAG_DIRTY
|
|
113
121
|
|
|
114
|
-
if (
|
|
122
|
+
if (!treesInProgress.length) {
|
|
115
123
|
treesInProgress.push(vNode)
|
|
116
|
-
nextUnitOfWork = vNode
|
|
117
124
|
return queueBeginWork()
|
|
118
125
|
}
|
|
119
126
|
|
|
120
|
-
for (let i = 0; i < treesInProgress.length; i++) {
|
|
121
|
-
const tree = treesInProgress[i]
|
|
122
|
-
if (tree !== vNode) continue
|
|
123
|
-
if (i < currentTreeIndex) {
|
|
124
|
-
// It was already processed; requeue it to the end
|
|
125
|
-
currentTreeIndex--
|
|
126
|
-
treesInProgress.splice(i, 1)
|
|
127
|
-
treesInProgress.push(tree)
|
|
128
|
-
}
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Check if this node is a descendant of any trees already queued
|
|
133
|
-
for (let i = 0; i < treesInProgress.length; i++) {
|
|
134
|
-
const tree = treesInProgress[i]
|
|
135
|
-
if (!vNodeContains(tree, vNode)) continue
|
|
136
|
-
|
|
137
|
-
if (i === currentTreeIndex) {
|
|
138
|
-
// It's a child of the currently worked-on tree
|
|
139
|
-
// If it's deeper within the same tree, we can skip
|
|
140
|
-
if (vNodeContains(nextUnitOfWork, vNode)) return
|
|
141
|
-
// If it's not in the current work subtree, move back up to it
|
|
142
|
-
nextUnitOfWork = vNode
|
|
143
|
-
} else if (i < currentTreeIndex) {
|
|
144
|
-
// It's a descendant of an already processed tree; treat as a new update
|
|
145
|
-
treesInProgress.push(vNode)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Check if this node contains any of the currently queued trees
|
|
152
|
-
let didReplaceTree = false
|
|
153
|
-
let shouldQueueAtEnd = false
|
|
154
|
-
for (let i = 0; i < treesInProgress.length; ) {
|
|
155
|
-
const tree = treesInProgress[i]
|
|
156
|
-
if (!vNodeContains(vNode, tree)) {
|
|
157
|
-
i++
|
|
158
|
-
continue
|
|
159
|
-
}
|
|
160
|
-
// This node contains another update root, replace it
|
|
161
|
-
|
|
162
|
-
if (i === currentTreeIndex) {
|
|
163
|
-
if (!didReplaceTree) {
|
|
164
|
-
treesInProgress.splice(i, 1, vNode)
|
|
165
|
-
nextUnitOfWork = vNode
|
|
166
|
-
didReplaceTree = true
|
|
167
|
-
i++ // advance past replaced node
|
|
168
|
-
} else {
|
|
169
|
-
treesInProgress.splice(i, 1)
|
|
170
|
-
// no increment
|
|
171
|
-
}
|
|
172
|
-
} else if (i < currentTreeIndex) {
|
|
173
|
-
currentTreeIndex--
|
|
174
|
-
treesInProgress.splice(i, 1)
|
|
175
|
-
if (!didReplaceTree) {
|
|
176
|
-
shouldQueueAtEnd = true
|
|
177
|
-
didReplaceTree = true
|
|
178
|
-
}
|
|
179
|
-
// no increment
|
|
180
|
-
} else {
|
|
181
|
-
// i > currentTreeIndex
|
|
182
|
-
treesInProgress.splice(i, 1)
|
|
183
|
-
if (!didReplaceTree) {
|
|
184
|
-
shouldQueueAtEnd = true
|
|
185
|
-
didReplaceTree = true
|
|
186
|
-
}
|
|
187
|
-
// no increment
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
if (!shouldQueueAtEnd && didReplaceTree) {
|
|
191
|
-
return
|
|
192
|
-
}
|
|
193
|
-
// If it doesn't overlap with any queued tree, queue as new independent update root
|
|
194
127
|
treesInProgress.push(vNode)
|
|
195
128
|
}
|
|
196
129
|
|
|
@@ -199,9 +132,13 @@ function queueDelete(vNode: VNode) {
|
|
|
199
132
|
deletions.push(vNode)
|
|
200
133
|
}
|
|
201
134
|
|
|
135
|
+
const depthSort = (a: VNode, b: VNode) => b.depth - a.depth
|
|
136
|
+
|
|
137
|
+
let currentWorkRoot: VNode | null = null
|
|
138
|
+
|
|
202
139
|
function doWork(): void {
|
|
203
140
|
if (__DEV__) {
|
|
204
|
-
const n =
|
|
141
|
+
const n = deletions[0] ?? treesInProgress[0]
|
|
205
142
|
if (n) {
|
|
206
143
|
appCtx = getVNodeAppContext(n)!
|
|
207
144
|
window.__kiru?.profilingContext?.beginTick(appCtx)
|
|
@@ -210,22 +147,32 @@ function doWork(): void {
|
|
|
210
147
|
}
|
|
211
148
|
}
|
|
212
149
|
|
|
213
|
-
|
|
214
|
-
nextUnitOfWork =
|
|
215
|
-
performUnitOfWork(nextUnitOfWork) ??
|
|
216
|
-
treesInProgress[++currentTreeIndex] ??
|
|
217
|
-
queueBlockedContextDependencyRoots()
|
|
218
|
-
}
|
|
150
|
+
let len = 1
|
|
219
151
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
152
|
+
onBeforeFlushDomChanges()
|
|
153
|
+
while (treesInProgress.length) {
|
|
154
|
+
if (treesInProgress.length > len) {
|
|
155
|
+
treesInProgress.sort(depthSort)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
currentWorkRoot = treesInProgress.shift()!
|
|
159
|
+
len = treesInProgress.length
|
|
160
|
+
|
|
161
|
+
const flags = currentWorkRoot.flags
|
|
162
|
+
if (flags & FLAG_DELETION) continue
|
|
163
|
+
if (flags & FLAG_DIRTY) {
|
|
164
|
+
let n: VNode | void = currentWorkRoot
|
|
165
|
+
while ((n = performUnitOfWork(n))) {}
|
|
166
|
+
|
|
167
|
+
while (deletions.length) {
|
|
168
|
+
commitDeletion(deletions.pop()!)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
commitWork(currentWorkRoot)
|
|
172
|
+
currentWorkRoot.flags &= ~FLAG_DIRTY
|
|
173
|
+
}
|
|
228
174
|
}
|
|
175
|
+
onAfterFlushDomChanges()
|
|
229
176
|
|
|
230
177
|
isImmediateEffectsMode = true
|
|
231
178
|
flushEffects(preEffects)
|
|
@@ -253,39 +200,6 @@ function doWork(): void {
|
|
|
253
200
|
}
|
|
254
201
|
}
|
|
255
202
|
|
|
256
|
-
function queueBlockedContextDependencyRoots(): VNode | null {
|
|
257
|
-
if (pendingContextChanges.size === 0) return null
|
|
258
|
-
|
|
259
|
-
// TODO: it's possible that a 'job' created by this process is
|
|
260
|
-
// blocked by a parent memo after a queueUpdate -> replaceTree action.
|
|
261
|
-
// To prevent this, we might need to add these to a distinct queue.
|
|
262
|
-
const jobRoots: VNode[] = []
|
|
263
|
-
pendingContextChanges.forEach((provider) => {
|
|
264
|
-
provider.props.dependents.forEach((dep) => {
|
|
265
|
-
if (!willMemoBlockUpdate(provider, dep)) return
|
|
266
|
-
for (let i = 0; i < jobRoots.length; i++) {
|
|
267
|
-
const root = jobRoots[i]
|
|
268
|
-
if (vNodeContains(root, dep)) {
|
|
269
|
-
if (willMemoBlockUpdate(root, dep)) {
|
|
270
|
-
// root is a parent of dep and there's a memo between them, prevent consolidation and queue as new root
|
|
271
|
-
break
|
|
272
|
-
}
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
if (vNodeContains(dep, root)) {
|
|
276
|
-
jobRoots[i] = dep
|
|
277
|
-
return
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
jobRoots.push(dep)
|
|
281
|
-
})
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
pendingContextChanges.clear()
|
|
285
|
-
treesInProgress.push(...jobRoots)
|
|
286
|
-
return jobRoots[0] ?? null
|
|
287
|
-
}
|
|
288
|
-
|
|
289
203
|
function performUnitOfWork(vNode: VNode): VNode | void {
|
|
290
204
|
let renderChild = true
|
|
291
205
|
try {
|
|
@@ -293,19 +207,17 @@ function performUnitOfWork(vNode: VNode): VNode | void {
|
|
|
293
207
|
if (typeof vNode.type === "string") {
|
|
294
208
|
updateHostComponent(vNode as DomVNode)
|
|
295
209
|
} else if (isExoticType(vNode.type)) {
|
|
296
|
-
if (vNode
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
pendingContextChanges.add(asProvider)
|
|
210
|
+
if (vNode?.type === $CONTEXT_PROVIDER) {
|
|
211
|
+
const {
|
|
212
|
+
props: { dependents, value },
|
|
213
|
+
prev,
|
|
214
|
+
} = vNode as ContextProviderNode<unknown>
|
|
215
|
+
|
|
216
|
+
if (dependents.size && prev && prev.props.value !== value) {
|
|
217
|
+
dependents.forEach(queueUpdate)
|
|
305
218
|
}
|
|
306
219
|
}
|
|
307
220
|
vNode.child = reconcileChildren(vNode, props.children)
|
|
308
|
-
queueNodeChildDeletions(vNode)
|
|
309
221
|
} else {
|
|
310
222
|
renderChild = updateFunctionComponent(vNode as FunctionVNode)
|
|
311
223
|
}
|
|
@@ -335,6 +247,11 @@ function performUnitOfWork(vNode: VNode): VNode | void {
|
|
|
335
247
|
})
|
|
336
248
|
}
|
|
337
249
|
|
|
250
|
+
if (vNode.deletions !== null) {
|
|
251
|
+
vNode.deletions.forEach(queueDelete)
|
|
252
|
+
vNode.deletions = null
|
|
253
|
+
}
|
|
254
|
+
|
|
338
255
|
if (renderChild && vNode.child) {
|
|
339
256
|
return vNode.child
|
|
340
257
|
}
|
|
@@ -351,7 +268,7 @@ function performUnitOfWork(vNode: VNode): VNode | void {
|
|
|
351
268
|
nextNode.effects = undefined
|
|
352
269
|
}
|
|
353
270
|
|
|
354
|
-
if (nextNode ===
|
|
271
|
+
if (nextNode === currentWorkRoot) return
|
|
355
272
|
if (nextNode.sibling) {
|
|
356
273
|
return nextNode.sibling
|
|
357
274
|
}
|
|
@@ -372,14 +289,17 @@ function updateFunctionComponent(vNode: FunctionVNode) {
|
|
|
372
289
|
vNode.arePropsEqual!(prev.memoizedProps, props) &&
|
|
373
290
|
!vNode.hmrUpdated
|
|
374
291
|
) {
|
|
292
|
+
vNode.flags |= FLAG_NOOP
|
|
375
293
|
return false
|
|
376
294
|
}
|
|
295
|
+
vNode.flags &= ~FLAG_NOOP
|
|
377
296
|
}
|
|
378
297
|
try {
|
|
379
298
|
node.current = vNode
|
|
380
299
|
let newChild
|
|
381
300
|
let renderTryCount = 0
|
|
382
301
|
do {
|
|
302
|
+
vNode.flags &= ~FLAG_DIRTY
|
|
383
303
|
isRenderDirtied = false
|
|
384
304
|
hookIndex.current = 0
|
|
385
305
|
|
|
@@ -413,7 +333,6 @@ function updateFunctionComponent(vNode: FunctionVNode) {
|
|
|
413
333
|
newChild = type(props)
|
|
414
334
|
} while (isRenderDirtied)
|
|
415
335
|
vNode.child = reconcileChildren(vNode, newChild)
|
|
416
|
-
queueNodeChildDeletions(vNode)
|
|
417
336
|
return true
|
|
418
337
|
} finally {
|
|
419
338
|
node.current = null
|
|
@@ -440,20 +359,12 @@ function updateHostComponent(vNode: DomVNode) {
|
|
|
440
359
|
// text should _never_ have children
|
|
441
360
|
if (type !== "#text") {
|
|
442
361
|
vNode.child = reconcileChildren(vNode, props.children)
|
|
443
|
-
queueNodeChildDeletions(vNode)
|
|
444
362
|
if (vNode.child && renderMode.current === "hydrate") {
|
|
445
363
|
hydrationStack.push(vNode.dom!)
|
|
446
364
|
}
|
|
447
365
|
}
|
|
448
366
|
}
|
|
449
367
|
|
|
450
|
-
function queueNodeChildDeletions(vNode: VNode) {
|
|
451
|
-
if (vNode.deletions) {
|
|
452
|
-
vNode.deletions.forEach(queueDelete)
|
|
453
|
-
vNode.deletions = null
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
368
|
function checkForTooManyConsecutiveDirtyRenders() {
|
|
458
369
|
if (consecutiveDirtyCount > CONSECUTIVE_DIRTY_LIMIT) {
|
|
459
370
|
throw new KiruError(
|
package/src/swr.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __DEV__ } from "./env.js"
|
|
2
2
|
import { useHook } from "./hooks/utils.js"
|
|
3
3
|
import { Signal } from "./signals/base.js"
|
|
4
|
+
import { AsyncTaskState } from "./types.utils.js"
|
|
4
5
|
import {
|
|
5
6
|
noop,
|
|
6
7
|
deepCompare,
|
|
@@ -9,23 +10,7 @@ import {
|
|
|
9
10
|
shallowCompare,
|
|
10
11
|
} from "./utils.js"
|
|
11
12
|
|
|
12
|
-
export type UseSWRState<T> =
|
|
13
|
-
| {
|
|
14
|
-
data: null
|
|
15
|
-
error: null
|
|
16
|
-
loading: true
|
|
17
|
-
}
|
|
18
|
-
| {
|
|
19
|
-
data: T
|
|
20
|
-
error: null
|
|
21
|
-
loading: false
|
|
22
|
-
}
|
|
23
|
-
| {
|
|
24
|
-
data: null
|
|
25
|
-
error: UseSWRError
|
|
26
|
-
loading: false
|
|
27
|
-
}
|
|
28
|
-
) & {
|
|
13
|
+
export type UseSWRState<T> = AsyncTaskState<T, UseSWRError> & {
|
|
29
14
|
mutate: (callback: () => Promise<T>) => void
|
|
30
15
|
isMutating: Signal<boolean>
|
|
31
16
|
isValidating: Signal<boolean>
|
|
@@ -51,7 +36,7 @@ export type SWRRetryState = {
|
|
|
51
36
|
delay: number
|
|
52
37
|
} | null
|
|
53
38
|
|
|
54
|
-
export
|
|
39
|
+
export interface SWRCacheEntry<T> {
|
|
55
40
|
key: any
|
|
56
41
|
resource: Signal<SWRResourceState<T>>
|
|
57
42
|
fetcher: (args: any) => Promise<T>
|
|
@@ -65,7 +50,7 @@ export type SWRCacheEntry<T> = {
|
|
|
65
50
|
|
|
66
51
|
export type SWRCache = Map<string, SWRCacheEntry<any>>
|
|
67
52
|
|
|
68
|
-
export
|
|
53
|
+
export interface SWROptions {
|
|
69
54
|
/**
|
|
70
55
|
* Specify `false` to disable revalidation on focus
|
|
71
56
|
*/
|
|
@@ -103,19 +88,24 @@ export type SWRKey =
|
|
|
103
88
|
| undefined
|
|
104
89
|
| false
|
|
105
90
|
|
|
106
|
-
|
|
107
|
-
|
|
91
|
+
const SWRGlobalState = {
|
|
92
|
+
cache: null as any as SWRCache,
|
|
93
|
+
online: false,
|
|
94
|
+
}
|
|
108
95
|
|
|
109
96
|
if ("window" in globalThis) {
|
|
110
|
-
|
|
111
|
-
new Map()
|
|
97
|
+
if (__DEV__) {
|
|
98
|
+
SWRGlobalState.cache = window.__kiru!.SWRGlobalCache ??= new Map()
|
|
99
|
+
} else {
|
|
100
|
+
SWRGlobalState.cache = new Map()
|
|
101
|
+
}
|
|
112
102
|
|
|
113
|
-
|
|
103
|
+
SWRGlobalState.online = navigator.onLine
|
|
114
104
|
window.addEventListener("online", () => {
|
|
115
|
-
|
|
105
|
+
SWRGlobalState.online = true
|
|
116
106
|
})
|
|
117
107
|
window.addEventListener("offline", () => {
|
|
118
|
-
|
|
108
|
+
SWRGlobalState.online = false
|
|
119
109
|
})
|
|
120
110
|
|
|
121
111
|
let blurStart: number | null = null
|
|
@@ -127,11 +117,12 @@ if ("window" in globalThis) {
|
|
|
127
117
|
blurStart = null
|
|
128
118
|
if (blurDuration < 3_000) return // only trigger revalidation after 3 seconds
|
|
129
119
|
|
|
130
|
-
|
|
120
|
+
SWRGlobalState.cache.forEach((entry) => {
|
|
131
121
|
if (
|
|
132
122
|
entry.subscribers.size === 0 ||
|
|
133
123
|
entry.options.revalidateOnFocus === false ||
|
|
134
|
-
(entry.options.refetchWhenOffline === false &&
|
|
124
|
+
(entry.options.refetchWhenOffline === false &&
|
|
125
|
+
SWRGlobalState.online === false)
|
|
135
126
|
) {
|
|
136
127
|
return
|
|
137
128
|
}
|
|
@@ -171,16 +162,16 @@ export function preloadSWR<T>(
|
|
|
171
162
|
if (!("window" in globalThis)) return
|
|
172
163
|
|
|
173
164
|
const strKey = safeStringify(key, { functions: false })
|
|
174
|
-
if (!
|
|
165
|
+
if (!SWRGlobalState.cache.has(strKey)) {
|
|
175
166
|
const entry = createSWRCacheEntry(key, fetcher)
|
|
176
|
-
|
|
167
|
+
SWRGlobalState.cache.set(strKey, entry)
|
|
177
168
|
performFetch(entry)
|
|
178
169
|
}
|
|
179
170
|
}
|
|
180
171
|
|
|
181
172
|
export function getSWRState<T>(key: SWRKey): SWRCacheEntry<T> | null {
|
|
182
173
|
const strKey = safeStringify(key, { functions: false })
|
|
183
|
-
return
|
|
174
|
+
return SWRGlobalState.cache.get(strKey) ?? null
|
|
184
175
|
}
|
|
185
176
|
|
|
186
177
|
export function useSWR<T, K extends SWRKey>(
|
|
@@ -201,14 +192,14 @@ export function useSWR<T, K extends SWRKey>(
|
|
|
201
192
|
devtools: {
|
|
202
193
|
get: () => ({
|
|
203
194
|
key: hook.strKey,
|
|
204
|
-
value:
|
|
195
|
+
value: SWRGlobalState.cache.get(strKey)!,
|
|
205
196
|
}),
|
|
206
197
|
},
|
|
207
198
|
initialArgs: [key, options],
|
|
208
199
|
}
|
|
209
200
|
}
|
|
210
201
|
if (isHMR) {
|
|
211
|
-
const entry =
|
|
202
|
+
const entry = SWRGlobalState.cache.get(hook.strKey)
|
|
212
203
|
const [k, o] = hook.dev!.initialArgs
|
|
213
204
|
hook.dev!.initialArgs = [key, options]
|
|
214
205
|
|
|
@@ -239,10 +230,10 @@ export function useSWR<T, K extends SWRKey>(
|
|
|
239
230
|
hook.update = update
|
|
240
231
|
|
|
241
232
|
let isNewEntry = false
|
|
242
|
-
if (!
|
|
233
|
+
if (!SWRGlobalState.cache.has(strKey)) {
|
|
243
234
|
isNewEntry = true
|
|
244
235
|
entry = createSWRCacheEntry(key, fetcher)
|
|
245
|
-
|
|
236
|
+
SWRGlobalState.cache.set(strKey, entry)
|
|
246
237
|
|
|
247
238
|
entry.resource.subscribe(() => {
|
|
248
239
|
entry.subscribers.forEach((sub) => sub.update())
|
|
@@ -251,7 +242,7 @@ export function useSWR<T, K extends SWRKey>(
|
|
|
251
242
|
performFetch(entry)
|
|
252
243
|
}
|
|
253
244
|
|
|
254
|
-
entry ??=
|
|
245
|
+
entry ??= SWRGlobalState.cache.get(strKey)!
|
|
255
246
|
const subs = entry.subscribers
|
|
256
247
|
if (subs.size === 0) {
|
|
257
248
|
if (!isNewEntry) {
|
|
@@ -279,7 +270,7 @@ export function useSWR<T, K extends SWRKey>(
|
|
|
279
270
|
}
|
|
280
271
|
}
|
|
281
272
|
|
|
282
|
-
entry ??=
|
|
273
|
+
entry ??= SWRGlobalState.cache.get(strKey)!
|
|
283
274
|
const { resource, isMutating, isValidating } = entry
|
|
284
275
|
const { data, loading, error } = resource.peek()
|
|
285
276
|
|
package/src/transition.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { useRef } from "./hooks/useRef.js"
|
|
|
5
5
|
import { useState } from "./hooks/useState.js"
|
|
6
6
|
|
|
7
7
|
export type TransitionState = "entering" | "entered" | "exiting" | "exited"
|
|
8
|
-
|
|
8
|
+
interface TransitionProps {
|
|
9
9
|
in: boolean
|
|
10
10
|
/**
|
|
11
11
|
* Initial state of the transition
|