Skip to content

Commit d3c3963

Browse files
committed
Clean up and fix incorrect context setter
1 parent 3143304 commit d3c3963

File tree

3 files changed

+42
-39
lines changed

3 files changed

+42
-39
lines changed

src/__tests__/suspense.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe('renderPrepass', () => {
1818

1919
const Outer = () => {
2020
const start = Date.now()
21-
while (Date.now() - start < 11) {}
21+
while (Date.now() - start < 6) {}
2222
return <Inner />
2323
}
2424

src/index.js

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @flow
22

33
import React, { type Node, type Element } from 'react'
4-
import type { Visitor, Frame, AbstractElement } from './types'
4+
import type { Visitor, YieldFrame, Frame, AbstractElement } from './types'
55
import { visitChildren, resumeVisitChildren } from './visitor'
66
import { getChildrenArray } from './element'
77

@@ -28,49 +28,58 @@ let prevDispatcher = ReactCurrentDispatcher.current
2828
the queue. Hence we recursively look at suspended components in
2929
this queue, wait for their promises to resolve, and continue
3030
calling visitChildren on their children. */
31-
const flushFrames = (queue: Frame[], visitor: Visitor): Promise<void> => {
32-
if (queue.length === 0) {
33-
return Promise.resolve()
31+
const updateWithFrame = (
32+
frame: Frame,
33+
queue: Frame[],
34+
visitor: Visitor
35+
): Promise<void> => {
36+
if (frame.kind === 'frame.yield') {
37+
const yieldFrame: YieldFrame = frame
38+
39+
return new Promise(resolve => {
40+
setImmediate(() => {
41+
prevDispatcher = ReactCurrentDispatcher.current
42+
ReactCurrentDispatcher.current = Dispatcher
43+
resumeVisitChildren(yieldFrame, queue, visitor)
44+
ReactCurrentDispatcher.current = prevDispatcher
45+
resolve()
46+
})
47+
})
3448
}
3549

36-
const frame = queue.shift()
37-
3850
return frame.thenable.then(() => {
3951
prevDispatcher = ReactCurrentDispatcher.current
4052
ReactCurrentDispatcher.current = Dispatcher
4153

4254
let children = []
4355

4456
// Update the component after we've suspended to rerender it,
45-
// at which point we'll actually get its children and continue
46-
// walking the tree
57+
// at which point we'll actually get its children
4758
if (frame.kind === 'frame.class') {
48-
visitChildren(
49-
getChildrenArray(updateClassComponent(queue, frame)),
50-
queue,
51-
visitor
52-
)
59+
children = getChildrenArray(updateClassComponent(queue, frame))
5360
} else if (frame.kind === 'frame.hooks') {
54-
visitChildren(
55-
getChildrenArray(updateFunctionComponent(queue, frame)),
56-
queue,
57-
visitor
58-
)
61+
children = getChildrenArray(updateFunctionComponent(queue, frame))
5962
} else if (frame.kind === 'frame.lazy') {
60-
visitChildren(
61-
getChildrenArray(updateLazyComponent(queue, frame)),
62-
queue,
63-
visitor
64-
)
65-
} else if (frame.kind === 'frame.yield') {
66-
resumeVisitChildren(frame, queue, visitor)
63+
children = getChildrenArray(updateLazyComponent(queue, frame))
6764
}
6865

66+
// Now continue walking the previously suspended component's
67+
// children (which might also suspend)
68+
visitChildren(children, queue, visitor)
6969
ReactCurrentDispatcher.current = prevDispatcher
70-
return flushFrames(queue, visitor)
7170
})
7271
}
7372

73+
const flushFrames = (queue: Frame[], visitor: Visitor): Promise<void> => {
74+
if (queue.length === 0) {
75+
return Promise.resolve()
76+
}
77+
78+
return updateWithFrame(queue.shift(), queue, visitor).then(() =>
79+
flushFrames(queue, visitor)
80+
)
81+
}
82+
7483
const defaultVisitor = () => {}
7584

7685
const renderPrepass = (element: Node, visitor?: Visitor): Promise<void> => {

src/visitor.js

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ import {
5858
REACT_LAZY_TYPE
5959
} from './symbols'
6060

61-
const makeImmediatePromise = () => {
62-
return new Promise(resolve => {
63-
setImmediate(resolve)
64-
})
65-
}
66-
6761
const render = (
6862
type: ComponentType<DefaultProps> & ComponentStatics,
6963
props: DefaultProps,
@@ -171,7 +165,7 @@ const visitLoop = (
171165
) => {
172166
const start = Date.now()
173167

174-
while (traversalChildren.length > 0 && Date.now() - start <= 10) {
168+
while (traversalChildren.length > 0 && Date.now() - start <= 5) {
175169
const currChildren = traversalChildren[traversalChildren.length - 1]
176170
const currIndex = traversalIndex[traversalIndex.length - 1]++
177171

@@ -199,8 +193,8 @@ export const visitChildren = (
199193
) => {
200194
const traversalChildren: AbstractElement[][] = [init]
201195
const traversalIndex: number[] = [0]
202-
const traversalMap: Array<void | ContextMap> = [undefined]
203-
const traversalStore: Array<void | ContextEntry> = [undefined]
196+
const traversalMap: Array<void | ContextMap> = [flushPrevContextMap()]
197+
const traversalStore: Array<void | ContextEntry> = [flushPrevContextStore()]
204198

205199
visitLoop(
206200
traversalChildren,
@@ -212,11 +206,11 @@ export const visitChildren = (
212206
)
213207

214208
if (traversalChildren.length > 0) {
215-
queue.push({
209+
queue.unshift({
216210
contextMap: getCurrentContextMap(),
217211
contextStore: getCurrentContextStore(),
212+
thenable: Promise.resolve(),
218213
kind: 'frame.yield',
219-
thenable: makeImmediatePromise(),
220214
children: traversalChildren,
221215
index: traversalIndex,
222216
map: traversalMap,
@@ -232,7 +226,7 @@ export const resumeVisitChildren = (
232226
) => {
233227
setCurrentIdentity(null)
234228
setCurrentContextMap(frame.contextMap)
235-
setCurrentContextMap(frame.contextStore)
229+
setCurrentContextStore(frame.contextStore)
236230

237231
visitLoop(frame.children, frame.index, frame.map, frame.store, queue, visitor)
238232
}

0 commit comments

Comments
 (0)