text: /**
   * Copyright (c) Facebook, Inc. and its affiliates.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   *
   * @flow
   */
  
  import type {Fiber} from './ReactInternalTypes';
  
  import {
    resetCurrentFiber as resetCurrentDebugFiberInDEV,
    setCurrentFiber as setCurrentDebugFiberInDEV,
  } from './ReactCurrentFiber';
  import getComponentName from 'shared/getComponentName';
  import {StrictMode} from './ReactTypeOfMode';
  
  type FiberArray = Array<Fiber>;
  type FiberToFiberComponentsMap = Map<Fiber, FiberArray>;
  
  const ReactStrictModeWarnings = {
    recordUnsafeLifecycleWarnings(fiber: Fiber, instance: any): void {},
    flushPendingUnsafeLifecycleWarnings(): void {},
    recordLegacyContextWarning(fiber: Fiber, instance: any): void {},
    flushLegacyContextWarning(): void {},
    discardPendingWarnings(): void {},
  };
  
  if (__DEV__) {
    const findStrictRoot = (fiber: Fiber): Fiber | null => {
      let maybeStrictRoot = null;
  
      let node = fiber;
      while (node !== null) {
        if (node.mode & StrictMode) {
          maybeStrictRoot = node;
        }
        node = node.return;
      }
  
      return maybeStrictRoot;
    };
  
    const setToSortedString = set => {
      const array = [];
      set.forEach(value => {
        array.push(value);
      });
      return array.sort().join(', ');
    };
  
    let pendingComponentWillMountWarnings: Array<Fiber> = [];
    let pendingUNSAFE_ComponentWillMountWarnings: Array<Fiber> = [];
    let pendingComponentWillReceivePropsWarnings: Array<Fiber> = [];
    let pendingUNSAFE_ComponentWillReceivePropsWarnings: Array<Fiber> = [];
    let pendingComponentWillUpdateWarnings: Array<Fiber> = [];
    let pendingUNSAFE_ComponentWillUpdateWarnings: Array<Fiber> = [];
  
    // Tracks components we have already warned about.
    const didWarnAboutUnsafeLifecycles = new Set();
  
    ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = (
      fiber: Fiber,
      instance: any,
    ) => {
      // Dedup strategy: Warn once per component.
      if (didWarnAboutUnsafeLifecycles.has(fiber.type)) {
        return;
      }
  
      if (
        typeof instance.componentWillMount === 'function' &&
        // Don't warn about react-lifecycles-compat polyfilled components.
        instance.componentWillMount.__suppressDeprecationWarning !== true
      ) {
        pendingComponentWillMountWarnings.push(fiber);
      }
  
      if (
        fiber.mode & StrictMode &&
        typeof instance.UNSAFE_componentWillMount === 'function'
      ) {
        pendingUNSAFE_ComponentWillMountWarnings.push(fiber);
      }
  
      if (
        typeof instance.componentWillReceiveProps === 'function' &&
        instance.componentWillReceiveProps.__suppressDeprecationWarning !== true
      ) {
        pendingComponentWillReceivePropsWarnings.push(fiber);
      }
  
      if (
        fiber.mode & StrictMode &&
        typeof instance.UNSAFE_componentWillReceiveProps === 'function'
      ) {
        pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber);
      }
  
      if (
        typeof instance.componentWillUpdate === 'function' &&
        instance.componentWillUpdate.__suppressDeprecationWarning !== true
      ) {
        pendingComponentWillUpdateWarnings.push(fiber);
      }
  
      if (
        fiber.mode & StrictMode &&
        typeof instance.UNSAFE_componentWillUpdate === 'function'
      ) {
        pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber);
      }
    };
  
    ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = () => {
      // We do an initial pass to gather component names
      const componentWillMountUniqueNames = new Set();
      if (pendingComponentWillMountWarnings.length > 0) {
        pendingComponentWillMountWarnings.forEach(fiber => {
          componentWillMountUniqueNames.add(
            getComponentName(fiber.type) || 'Component',
          );
          didWarnAboutUnsafeLifecycles.add(fiber.type);
        });
        pendingComponentWillMountWarnings = [];
      }
  
      const UNSAFE_componentWillMountUniqueNames = new Set();
      if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) {
        pendingUNSAFE_ComponentWillMountWarnings.forEach(fiber => {
          UNSAFE_componentWillMountUniqueNames.add(
            getComponentName(fiber.type) || 'Component',
          );
          didWarnAboutUnsafeLifecycles.add(fiber.type);
        });
        pendingUNSAFE_ComponentWillMountWarnings = [];
      }
  
      const componentWillReceivePropsUniqueNames = new Set();
      if (pendingComponentWillReceivePropsWarnings.length > 0) {
        pendingComponentWillReceivePropsWarnings.forEach(fiber => {
          componentWillReceivePropsUniqueNames.add(
            getComponentName(fiber.type) || 'Component',
          );
          didWarnAboutUnsafeLifecycles.add(fiber.type);
        });
  
        pendingComponentWillReceivePropsWarnings = [];
      }
  
      const UNSAFE_componentWillReceivePropsUniqueNames = new Set();
      if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) {
        pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(fiber => {
          UNSAFE_componentWillReceivePropsUniqueNames.add(
            getComponentName(fiber.type) || 'Component',
          );
          didWarnAboutUnsafeLifecycles.add(fiber.type);
        });
  
        pendingUNSAFE_ComponentWillReceivePropsWarnings = [];
      }
  
      const componentWillUpdateUniqueNames = new Set();
      if (pendingComponentWillUpdateWarnings.length > 0) {
        pendingComponentWillUpdateWarnings.forEach(fiber => {
          componentWillUpdateUniqueNames.add(
            getComponentName(fiber.type) || 'Component',
          );
          didWarnAboutUnsafeLifecycles.add(fiber.type);
        });
  
        pendingComponentWillUpdateWarnings = [];
      }
  
      const UNSAFE_componentWillUpdateUniqueNames = new Set();
      if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) {
        pendingUNSAFE_ComponentWillUpdateWarnings.forEach(fiber => {
          UNSAFE_componentWillUpdateUniqueNames.add(
            getComponentName(fiber.type) || 'Component',
          );
          didWarnAboutUnsafeLifecycles.add(fiber.type);
        });
  
        pendingUNSAFE_ComponentWillUpdateWarnings = [];
      }
  
      // Finally, we flush all the warnings
      // UNSAFE_ ones before the deprecated ones, since they'll be 'louder'
      if (UNSAFE_componentWillMountUniqueNames.size > 0) {
        const sortedNames = setToSortedString(
          UNSAFE_componentWillMountUniqueNames,
        );
        console.error(
          'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +
            'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
            '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
            '\nPlease update the following components: %s',
          sortedNames,
        );
      }
  
      if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) {
        const sortedNames = setToSortedString(
          UNSAFE_componentWillReceivePropsUniqueNames,
        );
        console.error(
          'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' +
            'and may indicate bugs in your code. ' +
            'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
            '* Move data fetching code or side effects to componentDidUpdate.\n' +
            "* If you're updating state whenever props change, " +
            'refactor your code to use memoization techniques or move it to ' +
            'static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n' +
            '\nPlease update the following components: %s',
          sortedNames,
        );
      }
  
      if (UNSAFE_componentWillUpdateUniqueNames.size > 0) {
        const sortedNames = setToSortedString(
          UNSAFE_componentWillUpdateUniqueNames,
        );
        console.error(
          'Using UNSAFE_componentWillUpdate in strict mode is not recommended ' +
            'and may indicate bugs in your code. ' +
            'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
            '* Move data fetching code or side effects to componentDidUpdate.\n' +
            '\nPlease update the following components: %s',
          sortedNames,
        );
      }
  
      if (componentWillMountUniqueNames.size > 0) {
        const sortedNames = setToSortedString(componentWillMountUniqueNames);
  
        console.warn(
          'componentWillMount has been renamed, and is not recommended for use. ' +
            'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
            '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
            '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
            'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
            'To rename all deprecated lifecycles to their new names, you can run ' +
            '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
            '\nPlease update the following components: %s',
          sortedNames,
        );
      }
  
      if (componentWillReceivePropsUniqueNames.size > 0) {
        const sortedNames = setToSortedString(
          componentWillReceivePropsUniqueNames,
        );
  
        console.warn(
          'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
            'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
            '* Move data fetching code or side effects to componentDidUpdate.\n' +
            "* If you're updating state whenever props change, refactor your " +
            'code to use memoization techniques or move it to ' +
            'static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n' +
            '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
            'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
            'To rename all deprecated lifecycles to their new names, you can run ' +
            '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
            '\nPlease update the following components: %s',
          sortedNames,
        );
      }
  
      if (componentWillUpdateUniqueNames.size > 0) {
        const sortedNames = setToSortedString(componentWillUpdateUniqueNames);
  
        console.warn(
          'componentWillUpdate has been renamed, and is not recommended for use. ' +
            'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' +
            '* Move data fetching code or side effects to componentDidUpdate.\n' +
            '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
            'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
            'To rename all deprecated lifecycles to their new names, you can run ' +
            '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
            '\nPlease update the following components: %s',
          sortedNames,
        );
      }
    };
  
    let pendingLegacyContextWarning: FiberToFiberComponentsMap = new Map();
  
    // Tracks components we have already warned about.
    const didWarnAboutLegacyContext = new Set();
  
    ReactStrictModeWarnings.recordLegacyContextWarning = (
      fiber: Fiber,
      instance: any,
    ) => {
      const strictRoot = findStrictRoot(fiber);
      if (strictRoot === null) {
        console.error(
          'Expected to find a StrictMode component in a strict mode tree. ' +
            'This error is likely caused by a bug in React. Please file an issue.',
        );
        return;
      }
  
      // Dedup strategy: Warn once per component.
      if (didWarnAboutLegacyContext.has(fiber.type)) {
        return;
      }
  
      let warningsForRoot = pendingLegacyContextWarning.get(strictRoot);
  
      if (
        fiber.type.contextTypes != null ||
        fiber.type.childContextTypes != null ||
        (instance !== null && typeof instance.getChildContext === 'function')
      ) {
        if (warningsForRoot === undefined) {
          warningsForRoot = [];
          pendingLegacyContextWarning.set(strictRoot, warningsForRoot);
        }
        warningsForRoot.push(fiber);
      }
    };
  
    ReactStrictModeWarnings.flushLegacyContextWarning = () => {
      ((pendingLegacyContextWarning: any): FiberToFiberComponentsMap).forEach(
        (fiberArray: FiberArray, strictRoot) => {
          if (fiberArray.length === 0) {
            return;
          }
          const firstFiber = fiberArray[0];
  
          const uniqueNames = new Set();
          fiberArray.forEach(fiber => {
            uniqueNames.add(getComponentName(fiber.type) || 'Component');
            didWarnAboutLegacyContext.add(fiber.type);
          });
  
          const sortedNames = setToSortedString(uniqueNames);
  
          try {
            setCurrentDebugFiberInDEV(firstFiber);
            console.error(
              'Legacy context API has been detected within a strict-mode tree.' +
                '\n\nThe old API will be supported in all 16.x releases, but applications ' +
                'using it should migrate to the new version.' +
                '\n\nPlease update the following components: %s' +
                '\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context',
              sortedNames,
            );
          } finally {
            resetCurrentDebugFiberInDEV();
          }
        },
      );
    };
  
    ReactStrictModeWarnings.discardPendingWarnings = () => {
      pendingComponentWillMountWarnings = [];
      pendingUNSAFE_ComponentWillMountWarnings = [];
      pendingComponentWillReceivePropsWarnings = [];
      pendingUNSAFE_ComponentWillReceivePropsWarnings = [];
      pendingComponentWillUpdateWarnings = [];
      pendingUNSAFE_ComponentWillUpdateWarnings = [];
      pendingLegacyContextWarning = new Map();
    };
  }
  
  export default ReactStrictModeWarnings;
  