跳到主要内容

React Fiber 跟踪标记组件

一、作用

二、导出的常量

1. 过渡根

export const TransitionRoot = 0;

2. 过渡追踪标记

export const TransitionTracingMarker = 1;

三、处理过渡回调

export function processTransitionCallbacks(
pendingTransitions: PendingTransitionCallbacks,
endTime: number,
callbacks: TransitionTracingCallbacks,
): void {
if (enableTransitionTracing) {
if (pendingTransitions !== null) {
const transitionStart = pendingTransitions.transitionStart;
const onTransitionStart = callbacks.onTransitionStart;
if (transitionStart !== null && onTransitionStart != null) {
transitionStart.forEach(transition => {
if (transition.name != null) {
onTransitionStart(transition.name, transition.startTime);
}
});
}

const markerProgress = pendingTransitions.markerProgress;
const onMarkerProgress = callbacks.onMarkerProgress;
if (onMarkerProgress != null && markerProgress !== null) {
markerProgress.forEach((markerInstance, markerName) => {
if (markerInstance.transitions !== null) {
// TODO: Clone the suspense object so users can't modify it
// TODO: 克隆 suspense 对象,以便用户无法修改它
const pending =
markerInstance.pendingBoundaries !== null
? Array.from(markerInstance.pendingBoundaries.values())
: [];
markerInstance.transitions.forEach(transition => {
if (transition.name != null) {
onMarkerProgress(
transition.name,
markerName,
transition.startTime,
endTime,
pending,
);
}
});
}
});
}

const markerComplete = pendingTransitions.markerComplete;
const onMarkerComplete = callbacks.onMarkerComplete;
if (markerComplete !== null && onMarkerComplete != null) {
markerComplete.forEach((transitions, markerName) => {
transitions.forEach(transition => {
if (transition.name != null) {
onMarkerComplete(
transition.name,
markerName,
transition.startTime,
endTime,
);
}
});
});
}

const markerIncomplete = pendingTransitions.markerIncomplete;
const onMarkerIncomplete = callbacks.onMarkerIncomplete;
if (onMarkerIncomplete != null && markerIncomplete !== null) {
markerIncomplete.forEach(({ transitions, aborts }, markerName) => {
transitions.forEach(transition => {
const filteredAborts = [];
aborts.forEach(abort => {
switch (abort.reason) {
case 'marker': {
filteredAborts.push({
type: 'marker',
name: abort.name,
endTime,
});
break;
}
case 'suspense': {
filteredAborts.push({
type: 'suspense',
name: abort.name,
endTime,
});
break;
}
default: {
break;
}
}
});

if (filteredAborts.length > 0) {
if (transition.name != null) {
onMarkerIncomplete(
transition.name,
markerName,
transition.startTime,
filteredAborts,
);
}
}
});
});
}

const transitionProgress = pendingTransitions.transitionProgress;
const onTransitionProgress = callbacks.onTransitionProgress;
if (onTransitionProgress != null && transitionProgress !== null) {
transitionProgress.forEach((pending, transition) => {
if (transition.name != null) {
onTransitionProgress(
transition.name,
transition.startTime,
endTime,
Array.from(pending.values()),
);
}
});
}

const transitionComplete = pendingTransitions.transitionComplete;
const onTransitionComplete = callbacks.onTransitionComplete;
if (transitionComplete !== null && onTransitionComplete != null) {
transitionComplete.forEach(transition => {
if (transition.name != null) {
onTransitionComplete(
transition.name,
transition.startTime,
endTime,
);
}
});
}
}
}
}

四、推送根标记实例

备注
export function pushRootMarkerInstance(workInProgress: Fiber): void {
if (enableTransitionTracing) {
// On the root, every transition gets mapped to it's own map of
// suspense boundaries. The transition is marked as complete when
// the suspense boundaries map is empty. We do this because every
// transition completes at different times and depends on different
// suspense boundaries to complete. We store all the transitions
// along with its map of suspense boundaries in the root incomplete
// transitions map. Each entry in this map functions like a tracing
// marker does, so we can push it onto the marker instance stack
//
// 在根节点上,每个过渡都会映射到它自己的挂起边界映射。过渡在挂起边界映射为空时
// 被标记为完成。我们这样做是因为每个过渡完成的时间不同,并且取决于不同的挂起边
// 界。我们将所有过渡及其挂起边界映射存储在根节点的未完成过渡映射中。该映射中的
// 每个条目都像跟踪标记一样工作,因此我们可以将其推入标记实例栈中
const transitions = getWorkInProgressTransitions();
const root: FiberRoot = workInProgress.stateNode;

if (transitions !== null) {
transitions.forEach(transition => {
if (!root.incompleteTransitions.has(transition)) {
const markerInstance: TracingMarkerInstance = {
tag: TransitionRoot,
transitions: new Set([transition]),
pendingBoundaries: null,
aborts: null,
name: null,
};
root.incompleteTransitions.set(transition, markerInstance);
}
});
}

const markerInstances = [];
// For ever transition on the suspense boundary, we push the transition
// along with its map of pending suspense boundaries onto the marker
// instance stack.
//
// 对于挂起边界上的每个过渡,我们将该过渡及其待处理挂起边界的映射推入标记实例堆栈。
root.incompleteTransitions.forEach(markerInstance => {
markerInstances.push(markerInstance);
});
push(markerInstanceStack, markerInstances, workInProgress);
}
}

五、推送标记实例

备注
export function pushMarkerInstance(
workInProgress: Fiber,
markerInstance: TracingMarkerInstance,
): void {
if (enableTransitionTracing) {
if (markerInstanceStack.current === null) {
push(markerInstanceStack, [markerInstance], workInProgress);
} else {
push(
markerInstanceStack,
markerInstanceStack.current.concat(markerInstance),
workInProgress,
);
}
}
}

六、弹出根标记实例

备注
export function popRootMarkerInstance(workInProgress: Fiber) {
if (enableTransitionTracing) {
pop(markerInstanceStack, workInProgress);
}
}

七、弹出标记实例

备注
export function popMarkerInstance(workInProgress: Fiber): void {
if (enableTransitionTracing) {
pop(markerInstanceStack, workInProgress);
}
}

八、 获取标记实例

export function getMarkerInstances(): Array<TracingMarkerInstance> | null {
if (enableTransitionTracing) {
return markerInstanceStack.current;
}
return null;
}

九、常量

1. 标记实例堆栈

备注
// For every tracing marker, store a pointer to it. We will later access it
// to get the set of suspense boundaries that need to resolve before the
// tracing marker can be logged as complete
// This code lives separate from the ReactFiberTransition code because
// we push and pop on the tracing marker, not the suspense boundary
//
// 对于每个跟踪标记,存储一个指向它的指针。我们稍后会访问它
// 以获取在跟踪标记可以被记录为完成之前需要解析的挂起边界集合
// 这段代码与 ReactFiberTransition 代码分开,因为我们对跟踪标记进行入栈和出栈,而不是对挂起边界
const markerInstanceStack: StackCursor<Array<TracingMarkerInstance> | null> =
createCursor(null);