Repository: facebook/react
File: packages/react-reconciler/src/ReactProfilerTimer.js (JavaScript)

Code before:

// Like pop but it also adds the current elapsed time to the parent scope.
export function bubbleNestedEffectDurations(
  prevEffectDuration: number,
): number {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return 0;
  }
  const elapsedTime = profilerEffectDuration;
  profilerEffectDuration += prevEffectDuration;
  return elapsedTime;
}

export function resetComponentEffectTimers(): void {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return;
  }
  componentEffectStartTime = -1.1;
  componentEffectEndTime = -1.1;
}

export function pushComponentEffectStart(): number {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return 0;
  }
  componentEffectSpawnedUpdate = false; // Reset.
  const prevEffectStart = componentEffectStartTime;
  componentEffectStartTime = -1.1; // Track the next start.
  return prevEffectStart;
}

export function popComponentEffectStart(prevEffectStart: number): void {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return;
  }
  // If the parent component didn't have a start time, we let this current time persist.
  if (prevEffectStart >= 0) {
    // Otherwise, we restore the previous parent's start time.
    componentEffectStartTime = prevEffectStart;
  }
}

export function pushComponentEffectDuration(): number {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return 0;
  }
  const prevEffectDuration = componentEffectDuration;
  componentEffectDuration = -0; // Reset component level duration.
  return prevEffectDuration;
}


Review comment (suggestion):
There's no equivalent pop here. That means that this is not scoped to a single component and will leak to siblings. I believe it may also get reset in the case that an effect is in the beginning of the recursion.

I think another issue is that this probably makes this outlined instead of inlined.

The correct way would be to make another pushComponentEffectX with a paired popComponentEffectX. Just like pushComponentEffectDuration etc. do. So that the previous value can be stored and popped at the end.

Code after:

// Like pop but it also adds the current elapsed time to the parent scope.
export function bubbleNestedEffectDurations(
  prevEffectDuration: number,
): number {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return 0;
  }
  const elapsedTime = profilerEffectDuration;
  profilerEffectDuration += prevEffectDuration;
  return elapsedTime;
}

export function resetComponentEffectTimers(): void {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return;
  }
  componentEffectStartTime = -1.1;
  componentEffectEndTime = -1.1;
}

export function pushComponentEffectStart(): number {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return 0;
  }
  const prevEffectStart = componentEffectStartTime;
  componentEffectStartTime = -1.1; // Track the next start.
  return prevEffectStart;
}

export function popComponentEffectStart(prevEffectStart: number): void {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return;
  }
  // If the parent component didn't have a start time, we let this current time persist.
  if (prevEffectStart >= 0) {
    // Otherwise, we restore the previous parent's start time.
    componentEffectStartTime = prevEffectStart;
  }
}

export function pushComponentEffectDuration(): number {
  if (!enableProfilerTimer || !enableProfilerCommitHooks) {
    return 0;
  }
  const prevEffectDuration = componentEffectDuration;
  componentEffectDuration = -0; // Reset component level duration.
  return prevEffectDuration;
}

export function popComponentEffectDuration(prevEffectDuration: number): void {