1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {Lane, Lanes} from './ReactFiberLane';
    
  11. import type {Wakeable} from 'shared/ReactTypes';
    
  12. 
    
  13. import {enableDebugTracing} from 'shared/ReactFeatureFlags';
    
  14. 
    
  15. const nativeConsole: Object = console;
    
  16. let nativeConsoleLog: null | Function = null;
    
  17. 
    
  18. const pendingGroupArgs: Array<any> = [];
    
  19. let printedGroupIndex: number = -1;
    
  20. 
    
  21. function formatLanes(laneOrLanes: Lane | Lanes): string {
    
  22.   return '0b' + (laneOrLanes: any).toString(2).padStart(31, '0');
    
  23. }
    
  24. 
    
  25. function group(...groupArgs: Array<string>): void {
    
  26.   pendingGroupArgs.push(groupArgs);
    
  27. 
    
  28.   if (nativeConsoleLog === null) {
    
  29.     nativeConsoleLog = nativeConsole.log;
    
  30.     nativeConsole.log = log;
    
  31.   }
    
  32. }
    
  33. 
    
  34. function groupEnd(): void {
    
  35.   pendingGroupArgs.pop();
    
  36.   while (printedGroupIndex >= pendingGroupArgs.length) {
    
  37.     nativeConsole.groupEnd();
    
  38.     printedGroupIndex--;
    
  39.   }
    
  40. 
    
  41.   if (pendingGroupArgs.length === 0) {
    
  42.     nativeConsole.log = nativeConsoleLog;
    
  43.     nativeConsoleLog = null;
    
  44.   }
    
  45. }
    
  46. 
    
  47. function log(...logArgs: Array<mixed>): void {
    
  48.   if (printedGroupIndex < pendingGroupArgs.length - 1) {
    
  49.     for (let i = printedGroupIndex + 1; i < pendingGroupArgs.length; i++) {
    
  50.       const groupArgs = pendingGroupArgs[i];
    
  51.       nativeConsole.group(...groupArgs);
    
  52.     }
    
  53.     printedGroupIndex = pendingGroupArgs.length - 1;
    
  54.   }
    
  55.   if (typeof nativeConsoleLog === 'function') {
    
  56.     nativeConsoleLog(...logArgs);
    
  57.   } else {
    
  58.     nativeConsole.log(...logArgs);
    
  59.   }
    
  60. }
    
  61. 
    
  62. const REACT_LOGO_STYLE =
    
  63.   'background-color: #20232a; color: #61dafb; padding: 0 2px;';
    
  64. 
    
  65. export function logCommitStarted(lanes: Lanes): void {
    
  66.   if (__DEV__) {
    
  67.     if (enableDebugTracing) {
    
  68.       group(
    
  69.         `%c⚛️%c commit%c (${formatLanes(lanes)})`,
    
  70.         REACT_LOGO_STYLE,
    
  71.         '',
    
  72.         'font-weight: normal;',
    
  73.       );
    
  74.     }
    
  75.   }
    
  76. }
    
  77. 
    
  78. export function logCommitStopped(): void {
    
  79.   if (__DEV__) {
    
  80.     if (enableDebugTracing) {
    
  81.       groupEnd();
    
  82.     }
    
  83.   }
    
  84. }
    
  85. 
    
  86. const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
    
  87. // $FlowFixMe[incompatible-type]: Flow cannot handle polymorphic WeakMaps
    
  88. const wakeableIDs: WeakMap<Wakeable, number> = new PossiblyWeakMap();
    
  89. let wakeableID: number = 0;
    
  90. function getWakeableID(wakeable: Wakeable): number {
    
  91.   if (!wakeableIDs.has(wakeable)) {
    
  92.     wakeableIDs.set(wakeable, wakeableID++);
    
  93.   }
    
  94.   return ((wakeableIDs.get(wakeable): any): number);
    
  95. }
    
  96. 
    
  97. export function logComponentSuspended(
    
  98.   componentName: string,
    
  99.   wakeable: Wakeable,
    
  100. ): void {
    
  101.   if (__DEV__) {
    
  102.     if (enableDebugTracing) {
    
  103.       const id = getWakeableID(wakeable);
    
  104.       const display = (wakeable: any).displayName || wakeable;
    
  105.       log(
    
  106.         `%c⚛️%c ${componentName} suspended`,
    
  107.         REACT_LOGO_STYLE,
    
  108.         'color: #80366d; font-weight: bold;',
    
  109.         id,
    
  110.         display,
    
  111.       );
    
  112.       wakeable.then(
    
  113.         () => {
    
  114.           log(
    
  115.             `%c⚛️%c ${componentName} resolved`,
    
  116.             REACT_LOGO_STYLE,
    
  117.             'color: #80366d; font-weight: bold;',
    
  118.             id,
    
  119.             display,
    
  120.           );
    
  121.         },
    
  122.         () => {
    
  123.           log(
    
  124.             `%c⚛️%c ${componentName} rejected`,
    
  125.             REACT_LOGO_STYLE,
    
  126.             'color: #80366d; font-weight: bold;',
    
  127.             id,
    
  128.             display,
    
  129.           );
    
  130.         },
    
  131.       );
    
  132.     }
    
  133.   }
    
  134. }
    
  135. 
    
  136. export function logLayoutEffectsStarted(lanes: Lanes): void {
    
  137.   if (__DEV__) {
    
  138.     if (enableDebugTracing) {
    
  139.       group(
    
  140.         `%c⚛️%c layout effects%c (${formatLanes(lanes)})`,
    
  141.         REACT_LOGO_STYLE,
    
  142.         '',
    
  143.         'font-weight: normal;',
    
  144.       );
    
  145.     }
    
  146.   }
    
  147. }
    
  148. 
    
  149. export function logLayoutEffectsStopped(): void {
    
  150.   if (__DEV__) {
    
  151.     if (enableDebugTracing) {
    
  152.       groupEnd();
    
  153.     }
    
  154.   }
    
  155. }
    
  156. 
    
  157. export function logPassiveEffectsStarted(lanes: Lanes): void {
    
  158.   if (__DEV__) {
    
  159.     if (enableDebugTracing) {
    
  160.       group(
    
  161.         `%c⚛️%c passive effects%c (${formatLanes(lanes)})`,
    
  162.         REACT_LOGO_STYLE,
    
  163.         '',
    
  164.         'font-weight: normal;',
    
  165.       );
    
  166.     }
    
  167.   }
    
  168. }
    
  169. 
    
  170. export function logPassiveEffectsStopped(): void {
    
  171.   if (__DEV__) {
    
  172.     if (enableDebugTracing) {
    
  173.       groupEnd();
    
  174.     }
    
  175.   }
    
  176. }
    
  177. 
    
  178. export function logRenderStarted(lanes: Lanes): void {
    
  179.   if (__DEV__) {
    
  180.     if (enableDebugTracing) {
    
  181.       group(
    
  182.         `%c⚛️%c render%c (${formatLanes(lanes)})`,
    
  183.         REACT_LOGO_STYLE,
    
  184.         '',
    
  185.         'font-weight: normal;',
    
  186.       );
    
  187.     }
    
  188.   }
    
  189. }
    
  190. 
    
  191. export function logRenderStopped(): void {
    
  192.   if (__DEV__) {
    
  193.     if (enableDebugTracing) {
    
  194.       groupEnd();
    
  195.     }
    
  196.   }
    
  197. }
    
  198. 
    
  199. export function logForceUpdateScheduled(
    
  200.   componentName: string,
    
  201.   lane: Lane,
    
  202. ): void {
    
  203.   if (__DEV__) {
    
  204.     if (enableDebugTracing) {
    
  205.       log(
    
  206.         `%c⚛️%c ${componentName} forced update %c(${formatLanes(lane)})`,
    
  207.         REACT_LOGO_STYLE,
    
  208.         'color: #db2e1f; font-weight: bold;',
    
  209.         '',
    
  210.       );
    
  211.     }
    
  212.   }
    
  213. }
    
  214. 
    
  215. export function logStateUpdateScheduled(
    
  216.   componentName: string,
    
  217.   lane: Lane,
    
  218.   payloadOrAction: any,
    
  219. ): void {
    
  220.   if (__DEV__) {
    
  221.     if (enableDebugTracing) {
    
  222.       log(
    
  223.         `%c⚛️%c ${componentName} updated state %c(${formatLanes(lane)})`,
    
  224.         REACT_LOGO_STYLE,
    
  225.         'color: #01a252; font-weight: bold;',
    
  226.         '',
    
  227.         payloadOrAction,
    
  228.       );
    
  229.     }
    
  230.   }
    
  231. }