code: /**
   * 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 {Wakeable, Thenable} from 'shared/ReactTypes';
  
  import {unstable_getCacheForType} from 'react';
  import * as fs from 'fs/promises';
  import {isAbsolute, normalize} from 'path';
  
  const Pending = 0;
  const Resolved = 1;
  const Rejected = 2;
  
  type PendingRecord = {|
    status: 0,
    value: Wakeable,
    cache: null,
  |};
  
  type ResolvedRecord<T> = {|
    status: 1,
    value: T,
    cache: null | Array<mixed>,
  |};
  
  type RejectedRecord = {|
    status: 2,
    value: mixed,
    cache: null,
  |};
  
  type Record<T> = PendingRecord | ResolvedRecord<T> | RejectedRecord;
  
  function createRecordFromThenable<T>(thenable: Thenable<T>): Record<T> {
    const record: Record<T> = {
      status: Pending,
      value: thenable,
      cache: null,
    };
    thenable.then(
      value => {
        if (record.status === Pending) {
          const resolvedRecord = ((record: any): ResolvedRecord<T>);
          resolvedRecord.status = Resolved;
          resolvedRecord.value = value;
        }
      },
      err => {
        if (record.status === Pending) {
          const rejectedRecord = ((record: any): RejectedRecord);
          rejectedRecord.status = Rejected;
          rejectedRecord.value = err;
        }
      },
    );
    return record;
  }
  
  function readRecord<T>(record: Record<T>): ResolvedRecord<T> {
    if (record.status === Resolved) {
      // This is just a type refinement.
      return record;
    } else {
      throw record.value;
    }
  }
  
  // We don't want to normalize every path ourselves in production.
  // However, relative or non-normalized paths will lead to cache misses.
  // So we encourage the developer to fix it in DEV and normalize on their end.
  function checkPathInDev(path: string) {
    if (__DEV__) {
      if (!isAbsolute(path)) {
        console.error(
          'The provided path was not absolute: "%s". ' +
            'Convert it to an absolute path first.',
          path,
        );
      } else if (path !== normalize(path)) {
        console.error(
          'The provided path was not normalized: "%s". ' +
            'Convert it to a normalized path first.',
          path,
        );
      }
    }
  }
  
  function createAccessMap(): Map<string, Array<number | Record<void>>> {
    return new Map();
  }
  
  export function access(path: string, mode?: number): void {
    checkPathInDev(path);
    if (mode == null) {
      mode = 0; // fs.constants.F_OK
    }
    const map = unstable_getCacheForType(createAccessMap);
    let accessCache = map.get(path);
    if (!accessCache) {
      accessCache = [];
      map.set(path, accessCache);
    }
    let record;
    for (let i = 0; i < accessCache.length; i += 2) {
      const cachedMode: number = (accessCache[i]: any);
      if (mode === cachedMode) {
        const cachedRecord: Record<void> = (accessCache[i + 1]: any);
        record = cachedRecord;
        break;
      }
    }
    if (!record) {
      const thenable = fs.access(path, mode);
      record = createRecordFromThenable(thenable);
      accessCache.push(mode, record);
    }
    readRecord(record); // No return value.
  }
  
  function createLstatMap(): Map<string, Array<boolean | Record<mixed>>> {
    return new Map();
  }
  
  export function lstat(path: string, options?: {bigint?: boolean}): mixed {
    checkPathInDev(path);
    let bigint = false;
    if (options && options.bigint) {
      bigint = true;
    }
    const map = unstable_getCacheForType(createLstatMap);
    let lstatCache = map.get(path);
    if (!lstatCache) {
      lstatCache = [];
      map.set(path, lstatCache);
    }
    let record;
    for (let i = 0; i < lstatCache.length; i += 2) {
      const cachedBigint: boolean = (lstatCache[i]: any);
      if (bigint === cachedBigint) {
        const cachedRecord: Record<void> = (lstatCache[i + 1]: any);
        record = cachedRecord;
        break;
      }
    }
    if (!record) {
      const thenable = fs.lstat(path, {bigint});
      record = createRecordFromThenable(thenable);
      lstatCache.push(bigint, record);
    }
    const stats = readRecord(record).value;
    return stats;
  }
  
  function createReaddirMap(): Map<
    string,
    Array<string | boolean | Record<mixed>>,
  > {
    return new Map();
  }
  
  export function readdir(
    path: string,
    options?: string | {encoding?: string, withFileTypes?: boolean},
  ): mixed {
    checkPathInDev(path);
    let encoding = 'utf8';
    let withFileTypes = false;
    if (typeof options === 'string') {
      encoding = options;
    } else if (options != null) {
      if (options.encoding) {
        encoding = options.encoding;
      }
      if (options.withFileTypes) {
        withFileTypes = true;
      }
    }
    const map = unstable_getCacheForType(createReaddirMap);
    let readdirCache = map.get(path);
    if (!readdirCache) {
      readdirCache = [];
      map.set(path, readdirCache);
    }
    let record;
    for (let i = 0; i < readdirCache.length; i += 3) {
      const cachedEncoding: string = (readdirCache[i]: any);
      const cachedWithFileTypes: boolean = (readdirCache[i + 1]: any);
      if (encoding === cachedEncoding && withFileTypes === cachedWithFileTypes) {
        const cachedRecord: Record<void> = (readdirCache[i + 2]: any);
        record = cachedRecord;
        break;
      }
    }
    if (!record) {
      const thenable = fs.readdir(path, {encoding, withFileTypes});
      record = createRecordFromThenable(thenable);
      readdirCache.push(encoding, withFileTypes, record);
    }
    const files = readRecord(record).value;
    return files;
  }
  
  function createReadFileMap(): Map<string, Record<Buffer>> {
    return new Map();
  }
  
  export function readFile(
    path: string,
    options:
      | string
      | {
          encoding?: string | null,
          // Unsupported:
          flag?: string, // Doesn't make sense except "r"
          signal?: mixed, // We'll have our own signal
        },
  ): string | Buffer {
    checkPathInDev(path);
    const map = unstable_getCacheForType(createReadFileMap);
    let record = map.get(path);
    if (!record) {
      const thenable = fs.readFile(path);
      record = createRecordFromThenable(thenable);
      map.set(path, record);
    }
    const resolvedRecord = readRecord(record);
    const buffer: Buffer = resolvedRecord.value;
    if (!options) {
      return buffer;
    }
    let encoding;
    if (typeof options === 'string') {
      encoding = options;
    } else {
      const flag = options.flag;
      if (flag != null && flag !== 'r') {
        throw Error(
          'The flag option is not supported, and always defaults to "r".',
        );
      }
      if (options.signal) {
        throw Error('The signal option is not supported.');
      }
      encoding = options.encoding;
    }
    if (typeof encoding !== 'string') {
      return buffer;
    }
    const textCache = resolvedRecord.cache || (resolvedRecord.cache = []);
    for (let i = 0; i < textCache.length; i += 2) {
      if (textCache[i] === encoding) {
        return (textCache[i + 1]: any);
      }
    }
    const text = buffer.toString((encoding: any));
    textCache.push(encoding, text);
    return text;
  }
  
  function createReadlinkMap(): Map<string, Array<string | Record<mixed>>> {
    return new Map();
  }
  
  export function readlink(
    path: string,
    options?: string | {encoding?: string},
  ): mixed {
    checkPathInDev(path);
    let encoding = 'utf8';
    if (typeof options === 'string') {
      encoding = options;
    } else if (options != null) {
      if (options.encoding) {
        encoding = options.encoding;
      }
    }
    const map = unstable_getCacheForType(createReadlinkMap);
    let readlinkCache = map.get(path);
    if (!readlinkCache) {
      readlinkCache = [];
      map.set(path, readlinkCache);
    }
    let record;
    for (let i = 0; i < readlinkCache.length; i += 2) {
      const cachedEncoding: string = (readlinkCache[i]: any);
      if (encoding === cachedEncoding) {
        const cachedRecord: Record<void> = (readlinkCache[i + 1]: any);
        record = cachedRecord;
        break;
      }
    }
    if (!record) {
      const thenable = fs.readlink(path, {encoding});
      record = createRecordFromThenable(thenable);
      readlinkCache.push(encoding, record);
    }
    const linkString = readRecord(record).value;
    return linkString;
  }
  
  function createRealpathMap(): Map<string, Array<string | Record<mixed>>> {
    return new Map();
  }
  
  export function realpath(
    path: string,
    options?: string | {encoding?: string},
  ): mixed {
    checkPathInDev(path);
    let encoding = 'utf8';
    if (typeof options === 'string') {
      encoding = options;
    } else if (options != null) {
      if (options.encoding) {
        encoding = options.encoding;
      }
    }
    const map = unstable_getCacheForType(createRealpathMap);
    let realpathCache = map.get(path);
    if (!realpathCache) {
      realpathCache = [];
      map.set(path, realpathCache);
    }
    let record;
    for (let i = 0; i < realpathCache.length; i += 2) {
      const cachedEncoding: string = (realpathCache[i]: any);
      if (encoding === cachedEncoding) {
        const cachedRecord: Record<void> = (realpathCache[i + 1]: any);
        record = cachedRecord;
        break;
      }
    }
    if (!record) {
      const thenable = fs.realpath(path, {encoding});
      record = createRecordFromThenable(thenable);
      realpathCache.push(encoding, record);
    }
    const resolvedPath = readRecord(record).value;
    return resolvedPath;
  }
  
  function createStatMap(): Map<string, Array<boolean | Record<mixed>>> {
    return new Map();
  }
  
  export function stat(path: string, options?: {bigint?: boolean}): mixed {
    checkPathInDev(path);
    let bigint = false;
    if (options && options.bigint) {
      bigint = true;
    }
    const map = unstable_getCacheForType(createStatMap);
    let statCache = map.get(path);
    if (!statCache) {
      statCache = [];
      map.set(path, statCache);
    }
    let record;
    for (let i = 0; i < statCache.length; i += 2) {
      const cachedBigint: boolean = (statCache[i]: any);
      if (bigint === cachedBigint) {
        const cachedRecord: Record<void> = (statCache[i + 1]: any);
        record = cachedRecord;
        break;
      }
    }
    if (!record) {
      const thenable = fs.stat(path, {bigint});
      record = createRecordFromThenable(thenable);
      statCache.push(bigint, record);
    }
    const stats = readRecord(record).value;
    return stats;
  }
  